0024612: Wrong pcurve of the section curve
[occt.git] / src / IntWalk / IntWalk_PWalking_1.gxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 //-----------------------------
16 //--  IntWalk_PWalking_1.gxx
17 //-- 
18
19 #include <Precision.hxx>
20 #include <math_FunctionSetRoot.hxx>
21
22 #include <Geom_Surface.hxx>
23
24 //#define KELARG 20.0
25
26 //==================================================================================
27 // function : IntWalk_PWalking::IntWalk_PWalking
28 // purpose  :
29 // estimate of max step : To avoid abrupt changes 
30 // during change of isos 
31 //==================================================================================
32 void ComputePasInit(Standard_Real *pasuv,
33                     Standard_Real Um1,Standard_Real UM1,
34                     Standard_Real Vm1,Standard_Real VM1,
35                     Standard_Real Um2,Standard_Real UM2,
36                     Standard_Real Vm2,Standard_Real VM2,
37                     Standard_Real _Um1,Standard_Real _UM1,
38                     Standard_Real _Vm1,Standard_Real _VM1,
39                     Standard_Real _Um2,Standard_Real _UM2,
40                     Standard_Real _Vm2,Standard_Real _VM2,
41                     const ThePSurface& ,
42                     const ThePSurface& ,
43                     const Standard_Real Increment) 
44
45   Standard_Real du1=Abs(UM1-Um1);
46   Standard_Real dv1=Abs(VM1-Vm1);
47   Standard_Real du2=Abs(UM2-Um2);
48   Standard_Real dv2=Abs(VM2-Vm2);
49
50   Standard_Real _du1=Abs(_UM1-_Um1);
51   Standard_Real _dv1=Abs(_VM1-_Vm1);
52   Standard_Real _du2=Abs(_UM2-_Um2);
53   Standard_Real _dv2=Abs(_VM2-_Vm2);
54
55   //-- limit the reduction of uv box estimate to 0.01 natural box
56   //--  du1 : On box of Inter
57   //-- _du1 : On parametric space
58   if(_du1<1e50 && du1<0.01*_du1) du1=0.01*_du1;
59   if(_dv1<1e50 && dv1<0.01*_dv1) dv1=0.01*_dv1;
60   if(_du2<1e50 && du2<0.01*_du2) du2=0.01*_du2;
61   if(_dv2<1e50 && dv2<0.01*_dv2) dv2=0.01*_dv2;
62
63   pasuv[0]=Increment*du1;
64   pasuv[1]=Increment*dv1;
65   pasuv[2]=Increment*du2;
66   pasuv[3]=Increment*dv2;
67 }
68
69 //=======================================================================
70 //function : IsParallel
71 //purpose  : Checks if theLine is parallel of some boundary of given
72 //            surface (it is determined by theCheckSurf1 flag). 
73 //            Parallelism assumes small oscillations (swing is less or 
74 //            equal than theToler).
75 //            Small lines (if first and last parameters in the Surface 
76 //            are almost equal) are classified as parallel (as same as 
77 //            any point can be considered as parallel of any line).
78 //=======================================================================
79 static void IsParallel(const Handle(IntSurf_LineOn2S)& theLine,
80                   const Standard_Boolean theCheckSurf1,
81                   const Standard_Real theToler,
82                   Standard_Boolean& theIsUparallel,
83                   Standard_Boolean& theIsVparallel)
84 {
85   const Standard_Integer aNbPointsMAX = 23;
86
87   theIsUparallel = theIsVparallel = Standard_True;
88
89   Standard_Integer aNbPoints = theLine->NbPoints();
90   if(aNbPoints > aNbPointsMAX)
91   {
92     aNbPoints = aNbPointsMAX;
93   }
94   else if(aNbPoints < 3)
95   {
96     //Here we cannot estimate parallelism.
97     //Do all same as for small lines 
98     return;
99   }
100
101   Standard_Real aStep = IntToReal(theLine->NbPoints()) / aNbPoints;
102   Standard_Real aNPoint = 1.0;
103
104   Standard_Real aUmin = RealLast(), aUmax = RealFirst(), aVmin = RealLast(), aVmax = RealFirst();
105   for(Standard_Integer aNum = 1; aNum <= aNbPoints; aNum++, aNPoint += aStep)
106   {
107     if(aNPoint > aNbPoints)
108     {
109       aNPoint = aNbPoints;
110     }
111
112     Standard_Real u, v;
113     if(theCheckSurf1)
114       theLine->Value(RealToInt(aNPoint)).ParametersOnS1(u, v);
115     else
116       theLine->Value(RealToInt(aNPoint)).ParametersOnS2(u, v);
117
118     if(u < aUmin)
119       aUmin = u;
120
121     if(u > aUmax)
122       aUmax = u;
123
124     if(v < aVmin)
125       aVmin = v;
126
127     if(v > aVmax)
128       aVmax = v;
129   }
130
131   theIsVparallel = ((aUmax - aUmin) < theToler);
132   theIsUparallel = ((aVmax - aVmin) < theToler);
133 }
134
135 //=======================================================================
136 //function : Checking
137 //purpose  : Check, if given point is in surface's boundaries.
138 //            If "yes" then theFactTol = 0.0, else theFactTol is
139 //            equal maximal deviation.
140 //=======================================================================
141 static Standard_Boolean Checking( const Handle(Adaptor3d_HSurface)& theASurf1,
142                                   const Handle(Adaptor3d_HSurface)& theASurf2,
143                                   Standard_Real& theU1,
144                                   Standard_Real& theV1,
145                                   Standard_Real& theU2,
146                                   Standard_Real& theV2,
147                                   Standard_Real& theFactTol)
148 {
149   const Standard_Real aTol = Precision::PConfusion();
150   const Standard_Real aU1bFirst = theASurf1->FirstUParameter();
151   const Standard_Real aU1bLast = theASurf1->LastUParameter();
152   const Standard_Real aU2bFirst = theASurf2->FirstUParameter();
153   const Standard_Real aU2bLast = theASurf2->LastUParameter();
154   const Standard_Real aV1bFirst = theASurf1->FirstVParameter();
155   const Standard_Real aV1bLast = theASurf1->LastVParameter();
156   const Standard_Real aV2bFirst = theASurf2->FirstVParameter();
157   const Standard_Real aV2bLast = theASurf2->LastVParameter();
158
159   Standard_Boolean isOnOrIn = Standard_True;
160   theFactTol = 0.0;
161
162   Standard_Real aDelta = aU1bFirst - theU1;
163   if(aDelta > aTol)
164   {
165     theU1 = aU1bFirst;
166     theFactTol = Max(theFactTol, aDelta);
167     isOnOrIn = Standard_False;
168   }
169   
170   aDelta = theU1 - aU1bLast;
171   if(aDelta > aTol)
172   {
173     theU1 = aU1bLast;
174     theFactTol = Max(theFactTol, aDelta);
175     isOnOrIn = Standard_False;
176   }
177
178   aDelta = aV1bFirst - theV1;
179   if(aDelta > aTol)
180   {
181     theV1 = aV1bFirst;
182     theFactTol = Max(theFactTol, aDelta);
183     isOnOrIn = Standard_False;
184   }
185   
186   aDelta = theV1 - aV1bLast;
187   if(aDelta > aTol)
188   {
189     theV1 = aV1bLast;
190     theFactTol = Max(theFactTol, aDelta);
191     isOnOrIn = Standard_False;
192   }
193
194   aDelta = aU2bFirst - theU2;
195   if(aDelta > aTol)
196   {
197     theU2 = aU2bFirst;
198     theFactTol = Max(theFactTol, aDelta);
199     isOnOrIn = Standard_False;
200   }
201   
202   aDelta = theU2 - aU2bLast;
203   if(aDelta > aTol)
204   {
205     theU2 = aU2bLast;
206     theFactTol = Max(theFactTol, aDelta);
207     isOnOrIn = Standard_False;
208   }
209
210   aDelta = aV2bFirst - theV2;
211   if(aDelta > aTol)
212   {
213     theV2 = aV2bFirst;
214     theFactTol = Max(theFactTol, aDelta);
215     isOnOrIn = Standard_False;
216   }
217   
218   aDelta = theV2 - aV2bLast;
219   if(aDelta > aTol)
220   {
221     theV2 = aV2bLast;
222     theFactTol = Max(theFactTol, aDelta);
223     isOnOrIn = Standard_False;
224   }
225
226   return isOnOrIn;
227 }
228
229 //==================================================================================
230 // function : IntWalk_PWalking::IntWalk_PWalking
231 // purpose  : 
232 //==================================================================================
233 IntWalk_PWalking::IntWalk_PWalking(const ThePSurface& Caro1,
234                                    const ThePSurface& Caro2,
235                                    const Standard_Real TolTangency,
236                                    const Standard_Real Epsilon,
237                                    const Standard_Real Deflection,
238                                    const Standard_Real Increment ) 
239                                    :
240
241 done(Standard_True),
242 close(Standard_False),
243 fleche(Deflection),
244 tolconf(Epsilon),
245 sensCheminement(1),
246 myIntersectionOn2S(Caro1,Caro2,TolTangency),
247 STATIC_BLOCAGE_SUR_PAS_TROP_GRAND(0),
248 STATIC_PRECEDENT_INFLEXION(0)
249 {
250   Standard_Real KELARG=20.;
251   //
252   pasMax=Increment*0.2; //-- June 25 99 after problems with precision 
253   Um1 = ThePSurfaceTool::FirstUParameter(Caro1);
254   Vm1 = ThePSurfaceTool::FirstVParameter(Caro1);
255   UM1 = ThePSurfaceTool::LastUParameter(Caro1);
256   VM1 = ThePSurfaceTool::LastVParameter(Caro1);
257
258   Um2 = ThePSurfaceTool::FirstUParameter(Caro2);
259   Vm2 = ThePSurfaceTool::FirstVParameter(Caro2);
260   UM2 = ThePSurfaceTool::LastUParameter(Caro2);
261   VM2 = ThePSurfaceTool::LastVParameter(Caro2);
262
263   ResoU1 = ThePSurfaceTool::UResolution(Caro1,Precision::Confusion());
264   ResoV1 = ThePSurfaceTool::VResolution(Caro1,Precision::Confusion());
265
266   ResoU2 = ThePSurfaceTool::UResolution(Caro2,Precision::Confusion());
267   ResoV2 = ThePSurfaceTool::VResolution(Caro2,Precision::Confusion());
268
269   Standard_Real NEWRESO;
270   Standard_Real MAXVAL;
271   Standard_Real MAXVAL2;
272   //
273   MAXVAL  = Abs(Um1);  MAXVAL2 = Abs(UM1);
274   if(MAXVAL2 > MAXVAL) MAXVAL = MAXVAL2;
275   NEWRESO = ResoU1 * MAXVAL ;
276   if(NEWRESO > ResoU1 &&NEWRESO<10) {    ResoU1 = NEWRESO;  }
277
278
279   MAXVAL  = Abs(Um2);   MAXVAL2 = Abs(UM2);
280   if(MAXVAL2 > MAXVAL) MAXVAL = MAXVAL2;
281   NEWRESO = ResoU2 * MAXVAL ;
282   if(NEWRESO > ResoU2 && NEWRESO<10) {     ResoU2 = NEWRESO;  }
283
284
285   MAXVAL  = Abs(Vm1);  MAXVAL2 = Abs(VM1);
286   if(MAXVAL2 > MAXVAL) MAXVAL = MAXVAL2;
287   NEWRESO = ResoV1 * MAXVAL ;
288   if(NEWRESO > ResoV1 && NEWRESO<10) {     ResoV1 = NEWRESO;  }
289
290
291   MAXVAL  = Abs(Vm2);  MAXVAL2 = Abs(VM2);
292   if(MAXVAL2 > MAXVAL) MAXVAL = MAXVAL2;
293   NEWRESO = ResoV2 * MAXVAL ;
294   if(NEWRESO > ResoV2 && NEWRESO<10) {     ResoV2 = NEWRESO;  }
295
296   pasuv[0]=pasMax*Abs(UM1-Um1);
297   pasuv[1]=pasMax*Abs(VM1-Vm1);
298   pasuv[2]=pasMax*Abs(UM2-Um2);
299   pasuv[3]=pasMax*Abs(VM2-Vm2);
300
301   if(ResoU1>0.0001*pasuv[0]) ResoU1=0.00001*pasuv[0];
302   if(ResoV1>0.0001*pasuv[1]) ResoV1=0.00001*pasuv[1];
303   if(ResoU2>0.0001*pasuv[2]) ResoU2=0.00001*pasuv[2];
304   if(ResoV2>0.0001*pasuv[3]) ResoV2=0.00001*pasuv[3];
305
306
307   if(ThePSurfaceTool::IsUPeriodic(Caro1)==Standard_False) { 
308     //UM1+=KELARG*pasuv[0];  Um1-=KELARG*pasuv[0];
309   }
310   else { 
311     Standard_Real t = UM1-Um1; 
312     if(t<ThePSurfaceTool::UPeriod(Caro1)) { 
313       t=0.5*(ThePSurfaceTool::UPeriod(Caro1)-t);
314       t=(t>KELARG*pasuv[0])? KELARG*pasuv[0] : t;
315       UM1+=t;  Um1-=t;
316     }
317   }
318
319   if(ThePSurfaceTool::IsVPeriodic(Caro1)==Standard_False) { 
320     //VM1+=KELARG*pasuv[1];  Vm1-=KELARG*pasuv[1];
321   }
322   else { 
323     Standard_Real t = VM1-Vm1; 
324     if(t<ThePSurfaceTool::VPeriod(Caro1)) { 
325       t=0.5*(ThePSurfaceTool::VPeriod(Caro1)-t);
326       t=(t>KELARG*pasuv[1])? KELARG*pasuv[1] : t;
327       VM1+=t;  Vm1-=t;
328     }
329   }
330
331   if(ThePSurfaceTool::IsUPeriodic(Caro2)==Standard_False) { 
332     //UM2+=KELARG*pasuv[2];  Um2-=KELARG*pasuv[2];
333   }
334   else { 
335     Standard_Real t = UM2-Um2; 
336     if(t<ThePSurfaceTool::UPeriod(Caro2)) { 
337       t=0.5*(ThePSurfaceTool::UPeriod(Caro2)-t);
338       t=(t>KELARG*pasuv[2])? KELARG*pasuv[2] : t;
339       UM2+=t;  Um2-=t;
340     }
341   }
342
343   if(ThePSurfaceTool::IsVPeriodic(Caro2)==Standard_False) {   
344     //VM2+=KELARG*pasuv[3];  Vm2-=KELARG*pasuv[3];
345   }
346   else { 
347     Standard_Real t = VM2-Vm2; 
348     if(t<ThePSurfaceTool::VPeriod(Caro2)) { 
349       t=0.5*(ThePSurfaceTool::VPeriod(Caro2)-t);
350       t=(t>KELARG*pasuv[3])? KELARG*pasuv[3] : t;
351       VM2+=t;  Vm2-=t;
352     }
353   }
354
355   //-- ComputePasInit(pasuv,Um1,UM1,Vm1,VM1,Um2,UM2,Vm2,VM2,Caro1,Caro2);
356
357   for (Standard_Integer i = 0; i<=3;i++) {
358     if(pasuv[i]>10) 
359       pasuv[i] = 10; 
360     pasInit[i] = pasSav[i] = pasuv[i]; 
361   }
362
363
364 }
365 //==================================================================================
366 // function : IntWalk_PWalking
367 // purpose  : 
368 //==================================================================================
369 IntWalk_PWalking::IntWalk_PWalking(const ThePSurface& Caro1,
370                                    const ThePSurface& Caro2,
371                                    const Standard_Real TolTangency,
372                                    const Standard_Real Epsilon,
373                                    const Standard_Real Deflection,
374                                    const Standard_Real Increment, 
375                                    const Standard_Real U1,
376                                    const Standard_Real V1,
377                                    const Standard_Real U2, 
378                                    const Standard_Real V2)
379                                    :
380
381 done(Standard_True),
382 close(Standard_False),
383 fleche(Deflection),
384 tolconf(Epsilon),
385 sensCheminement(1),       
386 myIntersectionOn2S(Caro1,Caro2,TolTangency),
387 STATIC_BLOCAGE_SUR_PAS_TROP_GRAND(0),
388 STATIC_PRECEDENT_INFLEXION(0)
389 {
390   Standard_Real KELARG=20.;
391   //
392   pasMax=Increment*0.2; //-- June 25 99 after problems with precision 
393   //
394   Um1 = ThePSurfaceTool::FirstUParameter(Caro1);
395   Vm1 = ThePSurfaceTool::FirstVParameter(Caro1);
396   UM1 = ThePSurfaceTool::LastUParameter(Caro1);
397   VM1 = ThePSurfaceTool::LastVParameter(Caro1);
398
399   Um2 = ThePSurfaceTool::FirstUParameter(Caro2);
400   Vm2 = ThePSurfaceTool::FirstVParameter(Caro2);
401   UM2 = ThePSurfaceTool::LastUParameter(Caro2);
402   VM2 = ThePSurfaceTool::LastVParameter(Caro2);
403
404   ResoU1 = ThePSurfaceTool::UResolution(Caro1,Precision::Confusion());
405   ResoV1 = ThePSurfaceTool::VResolution(Caro1,Precision::Confusion());
406
407   ResoU2 = ThePSurfaceTool::UResolution(Caro2,Precision::Confusion());
408   ResoV2 = ThePSurfaceTool::VResolution(Caro2,Precision::Confusion());
409   //
410   Standard_Real NEWRESO, MAXVAL, MAXVAL2;
411   //
412   MAXVAL  = Abs(Um1);  
413   MAXVAL2 = Abs(UM1);
414   if(MAXVAL2 > MAXVAL) {
415     MAXVAL = MAXVAL2;
416   }
417   NEWRESO = ResoU1 * MAXVAL ;
418   if(NEWRESO > ResoU1) {
419     ResoU1 = NEWRESO;  
420   }
421   //
422   MAXVAL  = Abs(Um2);   
423   MAXVAL2 = Abs(UM2);
424   if(MAXVAL2 > MAXVAL){
425     MAXVAL = MAXVAL2;
426   }  
427   NEWRESO = ResoU2 * MAXVAL ;
428   if(NEWRESO > ResoU2) {
429     ResoU2 = NEWRESO;  
430   }
431   //
432   MAXVAL  = Abs(Vm1);  
433   MAXVAL2 = Abs(VM1);
434   if(MAXVAL2 > MAXVAL) {
435     MAXVAL = MAXVAL2;
436   }
437   NEWRESO = ResoV1 * MAXVAL ;
438   if(NEWRESO > ResoV1) {    
439     ResoV1 = NEWRESO; 
440   }
441   //
442   MAXVAL  = Abs(Vm2);  
443   MAXVAL2 = Abs(VM2);
444   if(MAXVAL2 > MAXVAL){
445     MAXVAL = MAXVAL2;
446   }  
447   NEWRESO = ResoV2 * MAXVAL ;
448   if(NEWRESO > ResoV2) {  
449     ResoV2 = NEWRESO;
450   }
451   //
452   pasuv[0]=pasMax*Abs(UM1-Um1);
453   pasuv[1]=pasMax*Abs(VM1-Vm1);
454   pasuv[2]=pasMax*Abs(UM2-Um2);
455   pasuv[3]=pasMax*Abs(VM2-Vm2);
456   //
457   if(ThePSurfaceTool::IsUPeriodic(Caro1)==Standard_False) { 
458     UM1+=KELARG*pasuv[0];  
459     Um1-=KELARG*pasuv[0];
460   }
461   else { 
462     Standard_Real t = UM1-Um1; 
463     if(t<ThePSurfaceTool::UPeriod(Caro1)) { 
464       t=0.5*(ThePSurfaceTool::UPeriod(Caro1)-t);
465       t=(t>KELARG*pasuv[0])? KELARG*pasuv[0] : t;
466       UM1+=t;  
467       Um1-=t;
468     }
469   }
470   //
471   if(ThePSurfaceTool::IsVPeriodic(Caro1)==Standard_False) { 
472     VM1+=KELARG*pasuv[1];
473     Vm1-=KELARG*pasuv[1];
474   }
475   else { 
476     Standard_Real t = VM1-Vm1; 
477     if(t<ThePSurfaceTool::VPeriod(Caro1)) { 
478       t=0.5*(ThePSurfaceTool::VPeriod(Caro1)-t);
479       t=(t>KELARG*pasuv[1])? KELARG*pasuv[1] : t;
480       VM1+=t;  Vm1-=t;
481     }
482   }
483   //
484   if(ThePSurfaceTool::IsUPeriodic(Caro2)==Standard_False) { 
485     UM2+=KELARG*pasuv[2];  
486     Um2-=KELARG*pasuv[2];
487   }
488   else { 
489     Standard_Real t = UM2-Um2; 
490     if(t<ThePSurfaceTool::UPeriod(Caro2)) { 
491       t=0.5*(ThePSurfaceTool::UPeriod(Caro2)-t);
492       t=(t>KELARG*pasuv[2])? KELARG*pasuv[2] : t;
493       UM2+=t;  
494       Um2-=t;
495     }
496   }
497
498   if(ThePSurfaceTool::IsVPeriodic(Caro2)==Standard_False) {   
499     VM2+=KELARG*pasuv[3];  
500     Vm2-=KELARG*pasuv[3];
501   }
502   else { 
503     Standard_Real t = VM2-Vm2; 
504     if(t<ThePSurfaceTool::VPeriod(Caro2)) { 
505       t=0.5*(ThePSurfaceTool::VPeriod(Caro2)-t);
506       t=(t>KELARG*pasuv[3])? KELARG*pasuv[3] : t;
507       VM2+=t;  
508       Vm2-=t;
509     }
510   }
511   //-- ComputePasInit(pasuv,Um1,UM1,Vm1,VM1,Um2,UM2,Vm2,VM2,Caro1,Caro2);
512
513   for (Standard_Integer i = 0; i<=3;i++) {
514     pasInit[i] = pasSav[i] = pasuv[i]; 
515   }  
516
517   if(ResoU1>0.0001*pasuv[0]) ResoU1=0.00001*pasuv[0];
518   if(ResoV1>0.0001*pasuv[1]) ResoV1=0.00001*pasuv[1];
519   if(ResoU2>0.0001*pasuv[2]) ResoU2=0.00001*pasuv[2];
520   if(ResoV2>0.0001*pasuv[3]) ResoV2=0.00001*pasuv[3];
521   //
522   TColStd_Array1OfReal Par(1,4);
523   Par(1) = U1;
524   Par(2) = V1;
525   Par(3) = U2;
526   Par(4) = V2;
527   Perform(Par);
528 }
529
530 //==================================================================================
531 // function : PerformFirstPoint
532 // purpose  : 
533 //==================================================================================
534 Standard_Boolean IntWalk_PWalking::PerformFirstPoint  (const TColStd_Array1OfReal& ParDep,
535                                                        IntSurf_PntOn2S& FirstPoint)   
536 {
537   sensCheminement = 1;
538   close = Standard_False;
539   //
540   Standard_Integer i;
541   TColStd_Array1OfReal Param(1,4);
542   //
543   for (i=1; i<=4; ++i) {
544     Param(i) = ParDep(i);
545   }
546   //-- calculate the first solution point
547   math_FunctionSetRoot  Rsnld(myIntersectionOn2S.Function());
548   //
549   myIntersectionOn2S.Perform(Param,Rsnld);
550   if (!myIntersectionOn2S.IsDone())  { 
551     return Standard_False;
552   }
553
554   if (myIntersectionOn2S.IsEmpty()) {
555     return Standard_False;
556   }
557
558   FirstPoint = myIntersectionOn2S.Point();
559   return Standard_True;
560 }
561 //==================================================================================
562 // function : Perform
563 // purpose  : 
564 //==================================================================================
565 void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep)    
566 {
567   Perform(ParDep,Um1,Vm1,Um2,Vm2,UM1,VM1,UM2,VM2);
568 }
569 //==================================================================================
570 // function : Perform
571 // purpose  : 
572 //==================================================================================
573 void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
574                                const Standard_Real u1min,
575                                const Standard_Real v1min,
576                                const Standard_Real u2min,
577                                const Standard_Real v2min,
578                                const Standard_Real u1max,
579                                const Standard_Real v1max,
580                                const Standard_Real u2max,
581                                const Standard_Real v2max)
582 {
583   const Standard_Real aSQDistMax = 1.0e-14;
584   //xf
585
586   Standard_Integer NbPasOKConseq=0;
587   Standard_Real pasMaxSV[4], aTmp;
588   TColStd_Array1OfReal Param(1,4);
589   IntImp_ConstIsoparametric ChoixIso;
590   //xt
591   //
592   done = Standard_False;
593   //
594   // Caro1 and Caro2
595   const ThePSurface& Caro1 =myIntersectionOn2S.Function().AuxillarSurface1();
596   const ThePSurface& Caro2 =myIntersectionOn2S.Function().AuxillarSurface2();
597   //
598   const Standard_Real UFirst1 = ThePSurfaceTool::FirstUParameter(Caro1);
599   const Standard_Real VFirst1 = ThePSurfaceTool::FirstVParameter(Caro1);
600   const Standard_Real ULast1  = ThePSurfaceTool::LastUParameter (Caro1);
601   const Standard_Real VLast1  = ThePSurfaceTool::LastVParameter (Caro1);
602
603   const Standard_Real UFirst2 = ThePSurfaceTool::FirstUParameter(Caro2);
604   const Standard_Real VFirst2 = ThePSurfaceTool::FirstVParameter(Caro2);
605   const Standard_Real ULast2  = ThePSurfaceTool::LastUParameter (Caro2);
606   const Standard_Real VLast2  = ThePSurfaceTool::LastVParameter (Caro2);
607   //
608   ComputePasInit(pasuv,u1min,u1max,v1min,v1max,u2min,u2max,v2min,v2max,
609     Um1,UM1,Vm1,VM1,Um2,UM2,Vm2,VM2,Caro1,Caro2,pasMax+pasMax);
610   //
611   if(pasuv[0]<100.0*ResoU1) {
612     pasuv[0]=100.0*ResoU1; 
613   }
614   if(pasuv[1]<100.0*ResoV1) {
615     pasuv[1]=100.0*ResoV1; 
616   }
617   if(pasuv[2]<100.0*ResoU2) {
618     pasuv[2]=100.0*ResoU2;
619   }
620   if(pasuv[3]<100.0*ResoV2) {
621     pasuv[3]=100.0*ResoV2;
622   }
623   //
624   for (Standard_Integer i=0; i<4; ++i)
625   {
626     if(pasuv[i]>10)
627     {
628       pasuv[i] = 10;
629     }
630
631     pasInit[i] = pasSav[i] = pasuv[i]; 
632   }
633   //
634   line = new IntSurf_LineOn2S ();
635   //
636   for (Standard_Integer i=1; i<=4; ++i)
637   {
638     aTmp=ParDep(i);
639     Param(i)=ParDep(i);
640   }
641   //-- reproduce steps uv connected to surfaces Caro1 and Caro2
642   //-- pasuv[] and pasSav[] are modified during the marching
643   for(Standard_Integer i = 0; i < 4; ++i)
644   {
645     pasMaxSV[i] = pasSav[i] = pasuv[i] = pasInit[i]; 
646   }
647
648   //-- calculate the first solution point
649   math_FunctionSetRoot  Rsnld(myIntersectionOn2S.Function());
650   //
651   ChoixIso = myIntersectionOn2S.Perform(Param,Rsnld);
652   if (!myIntersectionOn2S.IsDone())
653   {
654     return;
655   }
656
657   //
658   if (myIntersectionOn2S.IsEmpty())
659   {
660     return;
661   }
662   //
663   if(myIntersectionOn2S.IsTangent())
664   {
665     return;
666   }
667   //
668   Standard_Boolean Arrive, DejaReparti;
669   const Standard_Integer RejectIndexMAX = 250000;
670   Standard_Integer IncKey, RejectIndex;
671   gp_Pnt pf,pl;
672   //
673   DejaReparti = Standard_False;
674   IncKey = 0;
675   RejectIndex = 0;
676   //
677   previousPoint = myIntersectionOn2S.Point();
678   previoustg = Standard_False;
679   previousd  = myIntersectionOn2S.Direction();
680   previousd1 = myIntersectionOn2S.DirectionOnS1();
681   previousd2 = myIntersectionOn2S.DirectionOnS2();
682   indextg = 1;
683   tgdir   = previousd;
684   firstd1 = previousd1;
685   firstd2 = previousd2;
686   tgfirst = tglast = Standard_False;
687   choixIsoSav  =  ChoixIso;
688   //------------------------------------------------------------
689   //-- Test if the first point of marching corresponds 
690   //-- to a point on borders. 
691   //-- In this case, DejaReparti is initialized as True
692   //-- 
693   pf = previousPoint.Value();
694   Standard_Boolean bTestFirstPoint = Standard_True;
695
696   previousPoint.Parameters(Param(1),Param(2),Param(3),Param(4));
697   AddAPoint(line,previousPoint);
698   //
699   IntWalk_StatusDeflection Status = IntWalk_OK;
700   Standard_Boolean NoTestDeflection = Standard_False;
701   Standard_Real SvParam[4], f;
702   Standard_Integer LevelOfEmptyInmyIntersectionOn2S=0;
703   Standard_Integer LevelOfPointConfondu = 0; 
704   Standard_Integer LevelOfIterWithoutAppend = -1;
705   //
706   Arrive = Standard_False;
707   while(!Arrive) //010
708   {
709     LevelOfIterWithoutAppend++;
710     if(LevelOfIterWithoutAppend>20)
711     {
712       Arrive = Standard_True; 
713       if(DejaReparti) {
714         break;
715       }
716       RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
717       LevelOfIterWithoutAppend = 0;
718     }
719     //
720     // compute f
721     f = 0.;
722     switch (ChoixIso) { 
723       case IntImp_UIsoparametricOnCaro1: f = Abs(previousd1.X()); break;
724       case IntImp_VIsoparametricOnCaro1: f = Abs(previousd1.Y()); break;
725       case IntImp_UIsoparametricOnCaro2: f = Abs(previousd2.X()); break;
726       case IntImp_VIsoparametricOnCaro2: f = Abs(previousd2.Y()); break;
727       default:break;
728     }
729     //
730     if(f<0.1) {
731       f=0.1;
732     }
733     //
734     previousPoint.Parameters(Param(1),Param(2),Param(3),Param(4));
735     //
736     //--ofv.begin
737     Standard_Real aIncKey, aEps, dP1, dP2, dP3, dP4;
738     //
739     dP1 = sensCheminement * pasuv[0] * previousd1.X() /f;
740     dP2 = sensCheminement * pasuv[1] * previousd1.Y() /f;
741     dP3 = sensCheminement * pasuv[2] * previousd2.X() /f; 
742     dP4 = sensCheminement * pasuv[3] * previousd2.Y() /f;
743     //
744     aIncKey=5.*(Standard_Real)IncKey;
745     aEps=1.e-7;
746     if(ChoixIso == IntImp_UIsoparametricOnCaro1 && Abs(dP1) < aEps)
747     {
748       dP1 *= aIncKey;
749     }
750
751     if(ChoixIso == IntImp_VIsoparametricOnCaro1 && Abs(dP2) < aEps)
752     {
753       dP2 *= aIncKey;
754     }
755
756     if(ChoixIso == IntImp_UIsoparametricOnCaro2 && Abs(dP3) < aEps)
757     {
758       dP3 *= aIncKey;
759     }
760
761     if(ChoixIso == IntImp_VIsoparametricOnCaro2 && Abs(dP4) < aEps)
762     {
763       dP4 *= aIncKey;
764     }
765     //--ofv.end
766     //
767     Param(1) += dP1;
768     Param(2) += dP2;
769     Param(3) += dP3; 
770     Param(4) += dP4;
771     //==========================
772     SvParam[0]=Param(1); 
773     SvParam[1]=Param(2);
774     SvParam[2]=Param(3);
775     SvParam[3]=Param(4);
776     //
777     ChoixIso= myIntersectionOn2S.Perform(Param, Rsnld, ChoixIso);                  
778     //
779     if (!myIntersectionOn2S.IsDone())
780     {
781       //end of line, division
782       Arrive = Standard_False;
783       Param(1)=SvParam[0]; 
784       Param(2)=SvParam[1]; 
785       Param(3)=SvParam[2];
786       Param(4)=SvParam[3];
787       RepartirOuDiviser(DejaReparti, ChoixIso, Arrive);
788     }
789     else  //009 
790     {
791       //== Calculation of exact point from Param(.) is possible
792       if (myIntersectionOn2S.IsEmpty())
793       {
794         Standard_Real u1,v1,u2,v2;
795         previousPoint.Parameters(u1,v1,u2,v2);
796         //
797         Arrive = Standard_False;
798         if(u1<UFirst1 || u1>ULast1)
799         {
800           Arrive=Standard_True;
801         }       
802
803         if(u2<UFirst2 || u2>ULast2)
804         {
805           Arrive=Standard_True;
806         }
807
808         if(v1<VFirst1 || v1>VLast1)
809         {
810           Arrive=Standard_True;
811         }
812
813         if(v2<VFirst2 || v2>VLast2)
814         {
815           Arrive=Standard_True;
816         }
817
818         RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
819         LevelOfEmptyInmyIntersectionOn2S++;
820         //
821         if(LevelOfEmptyInmyIntersectionOn2S>10)
822         {
823           pasuv[0]=pasSav[0]; 
824           pasuv[1]=pasSav[1]; 
825           pasuv[2]=pasSav[2]; 
826           pasuv[3]=pasSav[3];
827         }
828       }
829       else //008
830       {
831         //============================================================
832         //== A point has been found :  T E S T   D E F L E C T I O N 
833         //============================================================
834         if(NoTestDeflection)
835         {
836           NoTestDeflection = Standard_False;
837         }                 
838         else
839         {
840           if(--LevelOfEmptyInmyIntersectionOn2S<=0)
841           {
842             LevelOfEmptyInmyIntersectionOn2S=0;
843             if(LevelOfIterWithoutAppend < 10)
844             {
845               Status = TestDeflection();
846             }                   
847             else
848             {
849               pasuv[0]*=0.5; 
850               pasuv[1]*=0.5; 
851               pasuv[2]*=0.5; 
852               pasuv[3]*=0.5;
853             }
854           }
855         }
856
857         //============================================================
858         //==       T r a i t e m e n t   s u r   S t a t u s        ==
859         //============================================================
860         if(LevelOfPointConfondu > 5)
861         { 
862           Status = IntWalk_ArretSurPoint; 
863           LevelOfPointConfondu = 0;  
864         }
865         //
866         if(Status==IntWalk_OK)
867         { 
868           NbPasOKConseq++;
869           if(NbPasOKConseq >= 5)
870           {
871             NbPasOKConseq=0;
872             Standard_Boolean pastroppetit;
873             Standard_Real t;
874             //
875             do
876             {
877               pastroppetit=Standard_True;
878               //
879               if(pasuv[0]<pasInit[0])
880               {
881                 t = (pasInit[0]-pasuv[0])*0.25;
882                 if(t>0.1*pasInit[0])
883                 {
884                   t=0.1*pasuv[0];
885                 }
886
887                 pasuv[0]+=t; 
888                 pastroppetit=Standard_False;
889               }
890
891               if(pasuv[1]<pasInit[1])
892               {
893                 t = (pasInit[1]-pasuv[1])*0.25;
894                 if(t>0.1*pasInit[1]) {
895                   t=0.1*pasuv[1];
896                 }               
897
898                 pasuv[1]+=t; 
899                 pastroppetit=Standard_False;
900               }
901
902               if(pasuv[2]<pasInit[2])
903               {
904                 t = (pasInit[2]-pasuv[2])*0.25;
905                 if(t>0.1*pasInit[2])
906                 {
907                   t=0.1*pasuv[2];
908                 }
909
910                 pasuv[2]+=t; 
911                 pastroppetit=Standard_False;
912               }
913
914               if(pasuv[3]<pasInit[3])
915               {
916                 t = (pasInit[3]-pasuv[3])*0.25;
917                 if(t>0.1*pasInit[3]) {
918                   t=0.1*pasuv[3];
919                 }
920                 pasuv[3]+=t; 
921                 pastroppetit=Standard_False;
922               }
923               if(pastroppetit)
924               {
925                 if(pasMax<0.1)
926                 {
927                   pasMax*=1.1;
928                   pasInit[0]*=1.1; 
929                   pasInit[1]*=1.1; 
930                   pasInit[2]*=1.1; 
931                   pasInit[3]*=1.1; 
932                 }
933                 else
934                 {
935                   pastroppetit=Standard_False;
936                 }
937               }
938             }
939             while(pastroppetit);
940           }
941         }//Status==IntWalk_OK
942         else
943           NbPasOKConseq=0;
944
945         //
946         switch(Status)//007 
947         {
948         case IntWalk_ArretSurPointPrecedent:
949           {
950             Arrive = Standard_False;
951             RepartirOuDiviser(DejaReparti, ChoixIso, Arrive);
952             break;
953           }
954         case IntWalk_PasTropGrand:
955           {
956             Param(1)=SvParam[0];
957             Param(2)=SvParam[1]; 
958             Param(3)=SvParam[2]; 
959             Param(4)=SvParam[3];
960
961             if(LevelOfIterWithoutAppend > 5)
962             {
963               if(pasSav[0]<pasInit[0])
964               {
965                 pasInit[0]-=(pasInit[0]-pasSav[0])*0.25;
966                 LevelOfIterWithoutAppend=0;
967               }
968
969               if(pasSav[1]<pasInit[1])
970               {
971                 pasInit[1]-=(pasInit[1]-pasSav[1])*0.25;
972                 LevelOfIterWithoutAppend=0;
973               }
974
975               if(pasSav[2]<pasInit[2])
976               {
977                 pasInit[2]-=(pasInit[2]-pasSav[2])*0.25;
978                 LevelOfIterWithoutAppend=0;
979               }
980
981               if(pasSav[3]<pasInit[3])
982               {
983                 pasInit[3]-=(pasInit[3]-pasSav[3])*0.25;
984                 LevelOfIterWithoutAppend=0;
985               }
986             }
987
988             break;
989           }
990         case IntWalk_PointConfondu:
991           {
992             LevelOfPointConfondu++;
993
994             if(LevelOfPointConfondu>5)
995             {
996               Standard_Boolean pastroppetit;
997               //
998               do
999               {
1000                 pastroppetit=Standard_True;
1001
1002                 if(pasuv[0]<pasInit[0])
1003                 {
1004                   pasuv[0]+=(pasInit[0]-pasuv[0])*0.25;
1005                   pastroppetit=Standard_False;
1006                 }
1007
1008                 if(pasuv[1]<pasInit[1])
1009                 {
1010                   pasuv[1]+=(pasInit[1]-pasuv[1])*0.25;
1011                   pastroppetit=Standard_False;
1012                 }
1013
1014                 if(pasuv[2]<pasInit[2])
1015                 {
1016                   pasuv[2]+=(pasInit[2]-pasuv[2])*0.25;
1017                   pastroppetit=Standard_False; 
1018                 }
1019
1020                 if(pasuv[3]<pasInit[3])
1021                 {
1022                   pasuv[3]+=(pasInit[3]-pasuv[3])*0.25;
1023                   pastroppetit=Standard_False;
1024                 }
1025
1026                 if(pastroppetit)
1027                 {
1028                   if(pasMax<0.1)
1029                   {
1030                     pasMax*=1.1;
1031                     pasInit[0]*=1.1;
1032                     pasInit[1]*=1.1;
1033                     pasInit[2]*=1.1;
1034                     pasInit[3]*=1.1; 
1035                   }
1036                   else
1037                   {
1038                     pastroppetit=Standard_False;
1039                   }
1040                 }
1041               }
1042               while(pastroppetit);
1043             }
1044
1045             break;
1046           }
1047         case IntWalk_OK:
1048         case IntWalk_ArretSurPoint://006
1049           {
1050             //=======================================================
1051             //== Stop Test t   :  Frame on Param(.)     ==
1052             //=======================================================
1053             //xft arrive here
1054             Arrive = TestArret(DejaReparti,Param,ChoixIso); 
1055             // JMB 30th December 1999. 
1056             // Some statement below should not be put in comment because they are useful.
1057             // See grid CTO 909 A1 which infinitely loops 
1058             if(Arrive==Standard_False && Status==IntWalk_ArretSurPoint)
1059             {
1060               Arrive=Standard_True;
1061 #ifdef DEB
1062               cout << "Compile with option DEB : if problems with intersection : ";
1063               cout << "IntWalk_PWalking_1.gxx (lbr le 1erdec98)"<<endl;
1064 #endif
1065             }
1066
1067             if(Arrive)
1068             {
1069               NbPasOKConseq = -10;
1070             }
1071
1072             if(!Arrive)//005
1073             {
1074               //=====================================================
1075               //== Param(.) is in the limits                       ==
1076               //==  and does not end a closed  line                ==
1077               //=====================================================
1078               //== Check on the current point of myInters
1079               Standard_Boolean pointisvalid = Standard_False;
1080               {
1081                 Standard_Real u1,v1,u2,v2; 
1082                 myIntersectionOn2S.Point().Parameters(u1,v1,u2,v2);
1083
1084                 //
1085                 if(u1 <= UM1  && u2 <= UM2 && v1 <= VM1 && 
1086                   v2 <= VM2  && u1 >= Um1 && u2 >= Um2 &&
1087                   v1 >= Vm1  && v2 >= Vm2)
1088                 {
1089                   pointisvalid=Standard_True;
1090                 }
1091               }
1092
1093               //
1094               if(pointisvalid)
1095               {
1096                 previousPoint = myIntersectionOn2S.Point();
1097                 previoustg = myIntersectionOn2S.IsTangent();
1098
1099                 if(!previoustg)
1100                 {
1101                   previousd  = myIntersectionOn2S.Direction();
1102                   previousd1 = myIntersectionOn2S.DirectionOnS1();
1103                   previousd2 = myIntersectionOn2S.DirectionOnS2();
1104                 }
1105                 //=====================================================
1106                 //== Check on the previous Point
1107                 {
1108                   Standard_Real u1,v1,u2,v2;
1109                   previousPoint.Parameters(u1,v1,u2,v2); 
1110                   if( u1 <= UM1  && u2 <= UM2 && v1 <= VM1 &&
1111                     v2 <= VM2  && u1 >= Um1 && u2 >= Um2 &&
1112                     v1 >= Vm1  && v2 >= Vm2)
1113                   {
1114                     pl = previousPoint.Value();
1115                     if(bTestFirstPoint)
1116                     {
1117                       if(pf.SquareDistance(pl) < aSQDistMax)
1118                       {
1119                         IncKey++;
1120                         if(IncKey == 5000)
1121                           return;
1122                         else
1123                           continue;
1124                       }
1125                       else
1126                       {
1127                         bTestFirstPoint = Standard_False;
1128                       }
1129                     }
1130                     //
1131                     AddAPoint(line,previousPoint);
1132                     RejectIndex++;
1133
1134                     if(RejectIndex >= RejectIndexMAX)
1135                     {
1136                       break;
1137                     }
1138
1139                     //
1140                     LevelOfIterWithoutAppend = 0;
1141                   }
1142                 }
1143               }//pointisvalid
1144               //====================================================
1145
1146               if(Status == IntWalk_ArretSurPoint)
1147               {
1148                 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1149               }
1150               else
1151               {
1152                 if (line->NbPoints() == 2)
1153                 {
1154                   pasSav[0] = pasuv[0];
1155                   pasSav[1] = pasuv[1];
1156                   pasSav[2] = pasuv[2];
1157                   pasSav[3] = pasuv[3];
1158                 }
1159               }
1160             }//005 if(!Arrive)
1161             else  //004
1162             {
1163               if(close)
1164               {
1165                 //================= la ligne est fermee ===============
1166                 AddAPoint(line,line->Value(1)); //ligne fermee
1167                 LevelOfIterWithoutAppend=0;
1168               }
1169               else    //$$$
1170               {
1171                 //====================================================
1172                 //== Param was not in the limits (was reframed)
1173                 //====================================================
1174                 Standard_Boolean bPrevNotTangent = !previoustg || !myIntersectionOn2S.IsTangent();
1175
1176                 IntImp_ConstIsoparametric SauvChoixIso = ChoixIso;
1177                 ChoixIso = myIntersectionOn2S.Perform(Param,Rsnld,ChoixIso);
1178                 //
1179                 if(!myIntersectionOn2S.IsEmpty()) //002
1180                 {
1181                   // mutially outpasses in the square or intersection in corner
1182
1183                   if(TestArret(Standard_True,Param,ChoixIso))
1184                   {
1185                     NbPasOKConseq = -10;
1186                     ChoixIso = myIntersectionOn2S.Perform(Param,Rsnld,ChoixIso);
1187
1188                     if(!myIntersectionOn2S.IsEmpty())
1189                     {
1190                       previousPoint = myIntersectionOn2S.Point();
1191                       previoustg = myIntersectionOn2S.IsTangent();
1192
1193                       if (!previoustg)
1194                       {
1195                         previousd  = myIntersectionOn2S.Direction();
1196                         previousd1 = myIntersectionOn2S.DirectionOnS1();
1197                         previousd2 = myIntersectionOn2S.DirectionOnS2();
1198                       }
1199
1200                       pl = previousPoint.Value();
1201
1202                       if(bTestFirstPoint)
1203                       {
1204                         if(pf.SquareDistance(pl) < aSQDistMax)
1205                         {
1206                           IncKey++;
1207                           if(IncKey == 5000)
1208                             return;
1209                           else
1210                             continue;
1211                         }
1212                         else
1213                         {
1214                           bTestFirstPoint = Standard_False;
1215                         }
1216                       }
1217                       //
1218                       AddAPoint(line,previousPoint);
1219                       RejectIndex++;
1220
1221                       if(RejectIndex >= RejectIndexMAX)
1222                       {
1223                         break;
1224                       }
1225
1226                       //
1227                       LevelOfIterWithoutAppend=0;
1228                       RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1229                     }
1230                     else
1231                     {
1232                       //fail framing divides the step
1233                       Arrive = Standard_False;
1234                       RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1235                       NoTestDeflection = Standard_True;
1236                       ChoixIso = SauvChoixIso;
1237                     }
1238                   }//if(TestArret())
1239                   else
1240                   {
1241                     // save the last point
1242                     // to revert to it if the current point is out of bounds
1243
1244                     IntSurf_PntOn2S previousPointSave = previousPoint;
1245                     Standard_Boolean previoustgSave   = previoustg;
1246                     gp_Dir previousdSave              = previousd;
1247                     gp_Dir2d previousd1Save           = previousd1;
1248                     gp_Dir2d previousd2Save           = previousd2;
1249
1250                     previousPoint = myIntersectionOn2S.Point();
1251                     previoustg = myIntersectionOn2S.IsTangent();
1252                     Arrive = Standard_False;
1253
1254                     if(!previoustg)
1255                     {
1256                       previousd  = myIntersectionOn2S.Direction();
1257                       previousd1 = myIntersectionOn2S.DirectionOnS1();
1258                       previousd2 = myIntersectionOn2S.DirectionOnS2();
1259                     }
1260
1261                     //========================================
1262                     //== Check on PreviousPoint @@
1263
1264                     {
1265                       Standard_Real u1,v1,u2,v2;
1266                       previousPoint.Parameters(u1,v1,u2,v2);
1267
1268                       //To save initial 2d points
1269                       gp_Pnt2d ParamPntOnS1(Param(1), Param(2));
1270                       gp_Pnt2d ParamPntOnS2(Param(3), Param(4));
1271
1272                       ///////////////////////////
1273                       Param(1) = u1;
1274                       Param(2) = v1;
1275                       Param(3) = u2;
1276                       Param(4) = v2;
1277                       //
1278
1279                       //xf
1280                       Standard_Boolean bFlag1, bFlag2;
1281                       Standard_Real aTol2D=1.e-11;
1282                       //
1283                       bFlag1=u1 >= Um1-aTol2D && v1 >= Vm1-aTol2D && u1 <= UM1+aTol2D && v1 <= VM1+aTol2D;
1284                       bFlag2=u2 >= Um2-aTol2D && v2 >= Vm2-aTol2D && u2 <= UM2+aTol2D && v2 <= VM2+aTol2D;
1285                       if (bFlag1 && bFlag2)
1286                       {
1287                         /*
1288                         if(u1 <= UM1  && u2 <= UM2 && v1 <= VM1 &&
1289                         v2 <= VM2  && u1 >= Um1 && u2 >= Um2 &&
1290                         v1 >= Vm1  && v2 >= Vm2)  {
1291                         */                      
1292                         //xt
1293                         pl = previousPoint.Value();
1294
1295                         if(bTestFirstPoint)
1296                         {
1297                           if(pf.SquareDistance(pl) < aSQDistMax)
1298                           {
1299                             IncKey++;
1300
1301                             if(IncKey == 5000)
1302                               return;
1303                             else
1304                               continue;
1305                           }
1306                           else
1307                           {
1308                             bTestFirstPoint = Standard_False;
1309                           }
1310                         }
1311
1312                         //To avoid walking around the same point
1313                         //in the tangent zone near a border
1314
1315                         if (previoustg)
1316                         {
1317                           Standard_Real prevU1, prevV1, prevU2, prevV2;
1318                           previousPointSave.Parameters(prevU1, prevV1, prevU2, prevV2);
1319                           gp_Pnt2d prevPntOnS1(prevU1, prevV1), prevPntOnS2(prevU2, prevV2);
1320                           gp_Pnt2d curPntOnS1(u1, v1), curPntOnS2(u2, v2);
1321                           gp_Vec2d PrevToParamOnS1(prevPntOnS1, ParamPntOnS1);
1322                           gp_Vec2d PrevToCurOnS1(prevPntOnS1, curPntOnS1);
1323                           gp_Vec2d PrevToParamOnS2(prevPntOnS2, ParamPntOnS2);
1324                           gp_Vec2d PrevToCurOnS2(prevPntOnS2, curPntOnS2);
1325                           Standard_Real MaxAngle = 3*M_PI/4;
1326
1327                           if (Abs(PrevToParamOnS1.Angle(PrevToCurOnS1)) > MaxAngle &&
1328                             Abs(PrevToParamOnS2.Angle(PrevToCurOnS2)) > MaxAngle)
1329                           {
1330                             Arrive = Standard_True;
1331                             break;
1332                           }
1333                         }
1334
1335                         ////////////////////////////////////////
1336                         AddAPoint(line,previousPoint);
1337                         RejectIndex++;
1338
1339                         if(RejectIndex >= RejectIndexMAX)
1340                         {
1341                           break;
1342                         }
1343
1344                         //
1345
1346                         LevelOfIterWithoutAppend=0;
1347                         Arrive = Standard_True;
1348                       }
1349                       else
1350                       {
1351                         // revert to the last correctly calculated point
1352                         previousPoint = previousPointSave;
1353                         previoustg    = previoustgSave;
1354                         previousd     = previousdSave;
1355                         previousd1    = previousd1Save;
1356                         previousd2    = previousd2Save;
1357                       }
1358                     }
1359
1360                     //
1361                     Standard_Boolean wasExtended = Standard_False;
1362
1363                     if(Arrive && myIntersectionOn2S.IsTangent() && bPrevNotTangent)
1364                     {
1365                       if(ExtendLineInCommonZone(SauvChoixIso, DejaReparti))
1366                       {
1367                         wasExtended = Standard_True;
1368                         Arrive = Standard_False;
1369                         ChoixIso = SauvChoixIso;
1370                       }
1371                     }
1372
1373                     RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1374
1375                     if(Arrive && 
1376                       myIntersectionOn2S.IsDone() && !myIntersectionOn2S.IsEmpty() &&
1377                       myIntersectionOn2S.IsTangent() && bPrevNotTangent &&
1378                       !wasExtended)
1379                     {
1380                       if(ExtendLineInCommonZone(SauvChoixIso, DejaReparti))
1381                       {
1382                         wasExtended = Standard_True;
1383                         Arrive = Standard_False;
1384                         ChoixIso = SauvChoixIso;
1385                       }
1386                     }
1387                   }//else !TestArret() $
1388                 }//$$ end successful framing on border (!myIntersectionOn2S.IsEmpty())
1389                 else
1390                 {
1391                   //echec framing on border; division of step 
1392                   Arrive = Standard_False;
1393                   NoTestDeflection = Standard_True;
1394                   RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1395                 }
1396               }//$$$ end framing on border (!close)
1397             }//004 fin TestArret return Arrive = True
1398           } // 006case IntWalk_ArretSurPoint:  end Processing Status = OK  or ArretSurPoint 
1399         } //007  switch(Status) 
1400       } //008 end processing point  (TEST DEFLECTION)
1401     } //009 end processing line (else if myIntersectionOn2S.IsDone())
1402   }  //010 end if first departure point allows marching  while (!Arrive)
1403
1404   done = Standard_True;
1405 }
1406 // ===========================================================================================================
1407 // function: ExtendLineInCommonZone
1408 // purpose:  Extends already computed line inside tangent zone in the direction given by theChoixIso.
1409 //           Returns Standard_True if the line was extended through tangent zone and the last computed point 
1410 //           is outside the tangent zone (but it is not put into the line). Otherwise returns Standard_False.
1411 // ===========================================================================================================
1412 Standard_Boolean IntWalk_PWalking::ExtendLineInCommonZone(const IntImp_ConstIsoparametric theChoixIso,
1413                                                           const Standard_Boolean          theDirectionFlag) 
1414 {
1415   Standard_Boolean bOutOfTangentZone = Standard_False;
1416   Standard_Boolean bStop = !myIntersectionOn2S.IsTangent();
1417   Standard_Integer dIncKey = 1;
1418   TColStd_Array1OfReal Param(1,4);
1419   IntWalk_StatusDeflection Status = IntWalk_OK;
1420   Standard_Integer nbIterWithoutAppend = 0;
1421   Standard_Integer nbEqualPoints = 0;
1422   Standard_Integer parit = 0;
1423   Standard_Integer uvit = 0;
1424   IntSurf_SequenceOfPntOn2S aSeqOfNewPoint;
1425
1426   while (!bStop) {
1427     nbIterWithoutAppend++;
1428
1429     if((nbIterWithoutAppend > 20) || (nbEqualPoints > 20)) {
1430 #ifdef DEB
1431       cout<<"Compile with option DEB:";
1432       cout<<"Infinite loop has detected. Stop iterations (IntWalk_PWalking_1.gxx)" << endl;
1433 #endif
1434       bStop = Standard_True;
1435       break;
1436     }
1437     Standard_Real f = 0.;
1438
1439     switch (theChoixIso)
1440     { 
1441     case IntImp_UIsoparametricOnCaro1: f = Abs(previousd1.X()); break;
1442     case IntImp_VIsoparametricOnCaro1: f = Abs(previousd1.Y()); break;
1443     case IntImp_UIsoparametricOnCaro2: f = Abs(previousd2.X()); break;
1444     case IntImp_VIsoparametricOnCaro2: f = Abs(previousd2.Y()); break;
1445     }
1446
1447     if(f<0.1) f=0.1;
1448
1449     previousPoint.Parameters(Param(1),Param(2),Param(3),Param(4));
1450
1451     Standard_Real dP1 = sensCheminement * pasuv[0] * previousd1.X() /f;
1452     Standard_Real dP2 = sensCheminement * pasuv[1] * previousd1.Y() /f;
1453     Standard_Real dP3 = sensCheminement * pasuv[2] * previousd2.X() /f; 
1454     Standard_Real dP4 = sensCheminement * pasuv[3] * previousd2.Y() /f;
1455
1456     if(theChoixIso == IntImp_UIsoparametricOnCaro1 && Abs(dP1) < 1.e-7) dP1 *= (5. * (Standard_Real)dIncKey);
1457     if(theChoixIso == IntImp_VIsoparametricOnCaro1 && Abs(dP2) < 1.e-7) dP2 *= (5. * (Standard_Real)dIncKey);
1458     if(theChoixIso == IntImp_UIsoparametricOnCaro2 && Abs(dP3) < 1.e-7) dP3 *= (5. * (Standard_Real)dIncKey);
1459     if(theChoixIso == IntImp_VIsoparametricOnCaro2 && Abs(dP4) < 1.e-7) dP4 *= (5. * (Standard_Real)dIncKey);
1460
1461     Param(1) += dP1;
1462     Param(2) += dP2;
1463     Param(3) += dP3; 
1464     Param(4) += dP4;
1465     Standard_Real SvParam[4];
1466     IntImp_ConstIsoparametric ChoixIso = theChoixIso;
1467
1468     for(parit = 0; parit < 4; parit++) {
1469       SvParam[parit] = Param(parit+1);
1470     }
1471     math_FunctionSetRoot  Rsnld(myIntersectionOn2S.Function());
1472     ChoixIso = myIntersectionOn2S.Perform(Param,Rsnld, theChoixIso);
1473
1474     if (!myIntersectionOn2S.IsDone()) {
1475       return bOutOfTangentZone;
1476     }
1477     else {
1478       if (myIntersectionOn2S.IsEmpty()) {
1479         return bOutOfTangentZone;
1480       }
1481
1482       Status = TestDeflection();
1483
1484       if(Status == IntWalk_OK) {
1485
1486         for(uvit = 0; uvit < 4; uvit++) {
1487           if(pasuv[uvit] < pasInit[uvit]) {
1488             pasuv[uvit] = pasInit[uvit];
1489           }
1490         }
1491       }
1492
1493       switch(Status) {
1494       case  IntWalk_ArretSurPointPrecedent:
1495         {
1496           bStop = Standard_True;
1497           bOutOfTangentZone = !myIntersectionOn2S.IsTangent();
1498           break;
1499         }
1500       case IntWalk_PasTropGrand:
1501         {
1502           for(parit = 0; parit < 4; parit++) {
1503             Param(parit+1) = SvParam[parit];
1504           }
1505           Standard_Boolean bDecrease = Standard_False;
1506
1507           for(uvit = 0; uvit < 4; uvit++) {
1508             if(pasSav[uvit] < pasInit[uvit]) { 
1509               pasInit[uvit] -= (pasInit[uvit] - pasSav[uvit]) * 0.1;
1510               bDecrease = Standard_True;
1511             }
1512           }
1513
1514           if(bDecrease) nbIterWithoutAppend--;
1515           break;
1516         }
1517       case IntWalk_PointConfondu:
1518         {
1519           for(uvit = 0; uvit < 4; uvit++) {
1520             if(pasuv[uvit] < pasInit[uvit]) {
1521               pasuv[uvit] += (pasInit[uvit] - pasuv[uvit]) * 0.1;
1522             }
1523           }
1524           break;
1525         }
1526       case IntWalk_OK:
1527       case IntWalk_ArretSurPoint:
1528         {
1529           //
1530           bStop = TestArret(theDirectionFlag, Param, ChoixIso);
1531           //
1532
1533           //
1534           if(!bStop) {
1535             Standard_Real u11,v11,u12,v12; 
1536             myIntersectionOn2S.Point().Parameters(u11,v11,u12,v12); 
1537             Standard_Real u21,v21,u22,v22;
1538             previousPoint.Parameters(u21,v21,u22,v22); 
1539
1540             if(((fabs(u11-u21) < ResoU1) && (fabs(v11-v21) < ResoV1)) ||
1541               ((fabs(u12-u22) < ResoU2) && (fabs(v12-v22) < ResoV2))) {
1542                 nbEqualPoints++;
1543             }
1544             else {
1545               nbEqualPoints = 0;
1546             }
1547           }
1548           //
1549
1550           bStop = bStop || !myIntersectionOn2S.IsTangent();
1551           bOutOfTangentZone = !myIntersectionOn2S.IsTangent();
1552
1553           if(!bStop) {
1554             Standard_Boolean pointisvalid = Standard_False;
1555             Standard_Real u1,v1,u2,v2; 
1556             myIntersectionOn2S.Point().Parameters(u1,v1,u2,v2); 
1557
1558             if(u1 <= UM1  && u2 <= UM2 && v1 <= VM1 && 
1559               v2 <= VM2  && u1 >= Um1 && u2 >= Um2 &&
1560               v1 >= Vm1  && v2 >= Vm2) 
1561               pointisvalid = Standard_True;
1562
1563             if(pointisvalid) {
1564               previousPoint = myIntersectionOn2S.Point();
1565               previoustg = myIntersectionOn2S.IsTangent();
1566
1567               if(!previoustg) {
1568                 previousd  = myIntersectionOn2S.Direction();
1569                 previousd1 = myIntersectionOn2S.DirectionOnS1();
1570                 previousd2 = myIntersectionOn2S.DirectionOnS2();
1571               }
1572               Standard_Boolean bAddPoint = Standard_True;
1573
1574               if(line->NbPoints() >= 1) {
1575                 gp_Pnt pf = line->Value(1).Value();
1576                 gp_Pnt pl = previousPoint.Value(); 
1577
1578                 if(pf.Distance(pl) < Precision::Confusion()) { 
1579                   dIncKey++; 
1580                   if(dIncKey == 5000) return bOutOfTangentZone; 
1581                   else bAddPoint = Standard_False;
1582                 }
1583               }
1584
1585               if(bAddPoint) {
1586                 aSeqOfNewPoint.Append(previousPoint);
1587                 nbIterWithoutAppend = 0;
1588               }
1589             }
1590
1591             if (line->NbPoints() == 2) {
1592               for(uvit = 0; uvit < 4; uvit++) {
1593                 pasSav[uvit] = pasuv[uvit]; 
1594               }
1595             }
1596
1597             if ( !pointisvalid ) {
1598               // decrease step if out of bounds
1599               // otherwise the same calculations will be 
1600               // repeated several times
1601               if ( ( u1 > UM1 ) || ( u1 < Um1 ) )
1602                 pasuv[0] *= 0.5;
1603
1604               if ( ( v1 > VM1 ) || ( v1 < Vm1 ) ) 
1605                 pasuv[1] *= 0.5;
1606
1607               if ( ( u2 > UM2 ) || ( u2 < Um2 ) )
1608                 pasuv[2] *= 0.5;
1609
1610               if ( ( v2 > VM2 ) || ( v2 < Vm2 ) )
1611                 pasuv[3] *= 0.5;
1612             }
1613           } // end if(!bStop)
1614           else { //if(bStop)
1615             if(close && (line->NbPoints() >= 1)) { 
1616
1617               if(!bOutOfTangentZone) {
1618                 aSeqOfNewPoint.Append(line->Value(1)); // line end
1619               }
1620               nbIterWithoutAppend = 0;
1621             }
1622             else {
1623               ChoixIso = myIntersectionOn2S.Perform(Param, Rsnld, theChoixIso);
1624
1625               if(myIntersectionOn2S.IsEmpty()) { 
1626                 bStop = !myIntersectionOn2S.IsTangent();
1627                 bOutOfTangentZone = !myIntersectionOn2S.IsTangent();
1628               }
1629               else {
1630                 Standard_Boolean bAddPoint = Standard_True;
1631                 Standard_Boolean pointisvalid = Standard_False;
1632
1633                 previousPoint = myIntersectionOn2S.Point();
1634                 Standard_Real u1,v1,u2,v2; 
1635                 previousPoint.Parameters(u1,v1,u2,v2); 
1636
1637                 if(u1 <= UM1  && u2 <= UM2 && v1 <= VM1 && 
1638                   v2 <= VM2  && u1 >= Um1 && u2 >= Um2 &&
1639                   v1 >= Vm1  && v2 >= Vm2) 
1640                   pointisvalid = Standard_True;
1641
1642                 if(pointisvalid) {
1643
1644                   if(line->NbPoints() >= 1) {
1645                     gp_Pnt pf = line->Value(1).Value();
1646                     gp_Pnt pl = previousPoint.Value(); 
1647
1648                     if(pf.Distance(pl) < Precision::Confusion()) { 
1649                       dIncKey++; 
1650                       if(dIncKey == 5000) return bOutOfTangentZone; 
1651                       else bAddPoint = Standard_False;
1652                     }
1653                   }
1654
1655                   if(bAddPoint && !bOutOfTangentZone) {
1656                     aSeqOfNewPoint.Append(previousPoint);
1657                     nbIterWithoutAppend = 0;
1658                   }
1659                 }
1660               }
1661             }
1662           }
1663           break;
1664         }
1665       default:
1666         {
1667           break;
1668         }
1669       }
1670     }
1671   }
1672   Standard_Boolean bExtendLine = Standard_False;
1673   Standard_Real u1 = 0., v1 = 0., u2 = 0., v2 = 0.; 
1674
1675   Standard_Integer pit = 0;
1676
1677   for(pit = 0; !bExtendLine && (pit < 2); pit++) {
1678     if(pit == 0)
1679       previousPoint.Parameters(u1,v1,u2,v2); 
1680     else {
1681       if(aSeqOfNewPoint.Length() > 0)
1682         aSeqOfNewPoint.Value(aSeqOfNewPoint.Length()).Parameters(u1,v1,u2,v2); 
1683       else
1684         break;
1685     }
1686
1687     if(((u1 - Um1) < ResoU1) ||
1688       ((UM1 - u1) < ResoU1) ||
1689       ((u2 - Um2) < ResoU2) ||
1690       ((UM2 - u2) < ResoU2) ||
1691       ((v1 - Vm1) < ResoV1) ||
1692       ((VM1 - v1) < ResoV1) ||
1693       ((v2 - Vm2) < ResoV2) ||
1694       ((VM2 - v2) < ResoV2))
1695       bExtendLine = Standard_True;
1696   }
1697
1698   if(!bExtendLine) {
1699     //    if(Status == IntWalk_OK || Status == IntWalk_ArretSurPoint) {
1700     if(Status == IntWalk_OK) {
1701       bExtendLine = Standard_True;
1702
1703       if(aSeqOfNewPoint.Length() > 1) {
1704         TColStd_Array1OfReal FirstParams(0, 3), LastParams(0, 3), Resolutions(0, 3);
1705         Resolutions(0) = ResoU1; Resolutions(1) = ResoV1; Resolutions(2) = ResoU2; Resolutions(3) = ResoV2;
1706
1707         aSeqOfNewPoint(1).Parameters(FirstParams.ChangeValue(0), FirstParams.ChangeValue(1),
1708           FirstParams.ChangeValue(2), FirstParams.ChangeValue(3));
1709         aSeqOfNewPoint(aSeqOfNewPoint.Length()).Parameters(LastParams.ChangeValue(0), 
1710           LastParams.ChangeValue(1),
1711           LastParams.ChangeValue(2), 
1712           LastParams.ChangeValue(3)); 
1713         Standard_Integer indexofiso = 0;
1714
1715         if(theChoixIso == IntImp_UIsoparametricOnCaro1) indexofiso = 0;
1716         if(theChoixIso == IntImp_VIsoparametricOnCaro1) indexofiso = 1;
1717         if(theChoixIso == IntImp_UIsoparametricOnCaro2) indexofiso = 2;
1718         if(theChoixIso == IntImp_VIsoparametricOnCaro2) indexofiso = 3;
1719
1720         Standard_Integer afirstindex = (indexofiso < 2) ? 0 : 2;
1721         gp_Vec2d aTangentZoneDir(gp_Pnt2d(FirstParams.Value(afirstindex), FirstParams.Value(afirstindex + 1)),
1722           gp_Pnt2d(LastParams.Value(afirstindex), LastParams.Value(afirstindex + 1)));
1723
1724         gp_Dir2d anIsoDir(0, 1);
1725
1726         if((indexofiso == 1) || (indexofiso == 3))
1727           anIsoDir = gp_Dir2d(1, 0);
1728
1729         if(aTangentZoneDir.SquareMagnitude() > gp::Resolution()) {
1730           Standard_Real piquota = M_PI*0.25;
1731
1732           if(fabs(aTangentZoneDir.Angle(anIsoDir)) > piquota) {
1733             Standard_Integer ii = 1, nextii = 2;
1734             gp_Vec2d d1(0, 0);
1735             Standard_Real asqresol = gp::Resolution();
1736             asqresol *= asqresol;
1737
1738             do {
1739               aSeqOfNewPoint(ii).Parameters(FirstParams.ChangeValue(0), FirstParams.ChangeValue(1),
1740                 FirstParams.ChangeValue(2), FirstParams.ChangeValue(3));
1741               aSeqOfNewPoint(ii + 1).Parameters(LastParams.ChangeValue(0), LastParams.ChangeValue(1),
1742                 LastParams.ChangeValue(2), LastParams.ChangeValue(3));
1743               d1 = gp_Vec2d(gp_Pnt2d(FirstParams.Value(afirstindex),
1744                 FirstParams.Value(afirstindex + 1)),
1745                 gp_Pnt2d(LastParams.Value(afirstindex),
1746                 LastParams.Value(afirstindex + 1)));
1747               ii++;
1748             }
1749             while((d1.SquareMagnitude() < asqresol) &&
1750               (ii < aSeqOfNewPoint.Length()));
1751
1752             nextii = ii;
1753
1754             while(nextii < aSeqOfNewPoint.Length()) {
1755
1756               gp_Vec2d nextd1(0, 0);
1757               Standard_Integer jj = nextii;
1758
1759               do {
1760                 aSeqOfNewPoint(jj).Parameters(FirstParams.ChangeValue(0), FirstParams.ChangeValue(1),
1761                   FirstParams.ChangeValue(2), FirstParams.ChangeValue(3));
1762                 aSeqOfNewPoint(jj + 1).Parameters(LastParams.ChangeValue(0), LastParams.ChangeValue(1),
1763                   LastParams.ChangeValue(2), LastParams.ChangeValue(3));
1764                 nextd1 = gp_Vec2d(gp_Pnt2d(FirstParams.Value(afirstindex),
1765                   FirstParams.Value(afirstindex + 1)),
1766                   gp_Pnt2d(LastParams.Value(afirstindex),
1767                   LastParams.Value(afirstindex + 1)));
1768                 jj++;
1769
1770               }
1771               while((nextd1.SquareMagnitude() < asqresol) &&
1772                 (jj < aSeqOfNewPoint.Length()));
1773               nextii = jj;
1774
1775               if(fabs(d1.Angle(nextd1)) > piquota) {
1776                 bExtendLine = Standard_False;
1777                 break;
1778               }
1779               d1 = nextd1;
1780             }
1781           }
1782           // end if(fabs(aTangentZoneDir.Angle(anIsoDir)
1783         }
1784       }
1785     }
1786   }
1787
1788   if(!bExtendLine) {
1789     return Standard_False;
1790   }
1791   Standard_Integer i = 0;
1792
1793   for(i = 1; i <= aSeqOfNewPoint.Length(); i++) {
1794     AddAPoint(line, aSeqOfNewPoint.Value(i));
1795   }
1796
1797   return bOutOfTangentZone;
1798 }
1799
1800 //=======================================================================
1801 //function : DistanceMinimizeByGradient
1802 //purpose  : 
1803 //=======================================================================
1804 Standard_Boolean IntWalk_PWalking::
1805   DistanceMinimizeByGradient( const Handle(Adaptor3d_HSurface)& theASurf1,
1806                               const Handle(Adaptor3d_HSurface)& theASurf2,
1807                               Standard_Real& theU1,
1808                               Standard_Real& theV1,
1809                               Standard_Real& theU2,
1810                               Standard_Real& theV2,
1811                               const Standard_Real theStep0U1V1,
1812                               const Standard_Real theStep0U2V2)
1813 {
1814   const Standard_Integer aNbIterMAX = 60;
1815   const Standard_Real aTol = 1.0e-14;
1816   Handle(Geom_Surface) aS1, aS2;
1817
1818   switch(theASurf1->GetType())
1819   {
1820   case GeomAbs_BezierSurface:
1821     aS1 = theASurf1->Surface().Bezier();
1822     break;
1823   case GeomAbs_BSplineSurface:
1824     aS1 = theASurf1->Surface().BSpline();
1825     break;
1826   default:
1827     return Standard_True;
1828   }
1829
1830   switch(theASurf2->GetType())
1831   {
1832   case GeomAbs_BezierSurface:
1833     aS2 = theASurf2->Surface().Bezier();
1834     break;
1835   case GeomAbs_BSplineSurface:
1836     aS2 = theASurf2->Surface().BSpline();
1837     break;
1838   default:
1839     return Standard_True;
1840   }
1841
1842   Standard_Boolean aStatus = Standard_False;
1843
1844   gp_Pnt aP1, aP2;
1845   gp_Vec aD1u, aD1v, aD2U, aD2V;
1846
1847   aS1->D1(theU1, theV1, aP1, aD1u, aD1v);
1848   aS2->D1(theU2, theV2, aP2, aD2U, aD2V);
1849
1850   Standard_Real aSQDistPrev = aP1.SquareDistance(aP2);
1851
1852   gp_Vec aP12(aP1, aP2);
1853
1854   Standard_Real aGradFu(-aP12.Dot(aD1u));
1855   Standard_Real aGradFv(-aP12.Dot(aD1v));
1856   Standard_Real aGradFU( aP12.Dot(aD2U));
1857   Standard_Real aGradFV( aP12.Dot(aD2V));
1858
1859   Standard_Real aSTEPuv = theStep0U1V1, aStepUV = theStep0U2V2;
1860
1861   Standard_Boolean flRepeat = Standard_True;
1862   Standard_Integer aNbIter = aNbIterMAX;
1863
1864   while(flRepeat)
1865   {
1866     Standard_Real anAdd = aGradFu*aSTEPuv;
1867     Standard_Real aPARu = (anAdd >= 0.0)?
1868             (theU1 - Max(anAdd, Epsilon(theU1))) :
1869             (theU1 + Max(-anAdd, Epsilon(theU1)));
1870     anAdd = aGradFv*aSTEPuv;
1871     Standard_Real aPARv = (anAdd >= 0.0)?
1872             (theV1 - Max(anAdd, Epsilon(theV1))) :
1873             (theV1 + Max(-anAdd, Epsilon(theV1)));
1874     anAdd = aGradFU*aStepUV;
1875     Standard_Real aParU = (anAdd >= 0.0)?
1876             (theU2 - Max(anAdd, Epsilon(theU2))) :
1877             (theU2 + Max(-anAdd, Epsilon(theU2)));
1878     anAdd = aGradFV*aStepUV;
1879     Standard_Real aParV = (anAdd >= 0.0)?
1880             (theV2 - Max(anAdd, Epsilon(theV2))) :
1881             (theV2 + Max(-anAdd, Epsilon(theV2)));
1882
1883     gp_Pnt aPt1, aPt2;
1884
1885     aS1->D1(aPARu, aPARv, aPt1, aD1u, aD1v);
1886     aS2->D1(aParU, aParV, aPt2, aD2U, aD2V);
1887
1888     Standard_Real aSQDist = aPt1.SquareDistance(aPt2);
1889
1890     if(aSQDist < aSQDistPrev)
1891     {
1892       aSQDistPrev = aSQDist;
1893       theU1 = aPARu;
1894       theV1 = aPARv;
1895       theU2 = aParU;
1896       theV2 = aParV;
1897
1898       aStatus = aSQDistPrev < aTol;
1899       aSTEPuv *= 1.2;
1900       aStepUV *= 1.2;
1901     }
1902     else
1903     {
1904       if(--aNbIter < 0)
1905       {
1906         flRepeat = Standard_False;
1907       }
1908       else
1909       {
1910         aS1->D1(theU1, theV1, aPt1, aD1u, aD1v);
1911         aS2->D1(theU2, theV2, aPt2, aD2U, aD2V);
1912
1913         gp_Vec aP12(aPt1, aPt2);
1914         aGradFu = -aP12.Dot(aD1u);
1915         aGradFv = -aP12.Dot(aD1v);
1916         aGradFU = aP12.Dot(aD2U);
1917         aGradFV = aP12.Dot(aD2V);
1918         aSTEPuv = theStep0U1V1;
1919         aStepUV = theStep0U2V2;
1920       }
1921     }
1922   }
1923
1924   return aStatus;
1925 }
1926
1927 //=======================================================================
1928 //function : DistanceMinimizeByExtrema
1929 //purpose  : 
1930 //=======================================================================
1931 Standard_Boolean IntWalk_PWalking::
1932   DistanceMinimizeByExtrema(const Handle(Adaptor3d_HSurface)& theASurf, 
1933                             const gp_Pnt& theP0,
1934                             Standard_Real& theU0,
1935                             Standard_Real& theV0,
1936                             const Standard_Real theStep0U,
1937                             const Standard_Real theStep0V)
1938 {
1939   const Standard_Real aTol = 1.0e-14;
1940   gp_Pnt aPS;
1941   gp_Vec aD1Su, aD1Sv, aD2Su, aD2Sv, aD2SuvTemp;
1942   Standard_Real aSQDistPrev = RealLast();
1943   Standard_Real aU = theU0, aV = theV0;
1944   
1945   Standard_Integer aNbIter = 10;
1946   do
1947   {
1948     theASurf->D2(aU, aV, aPS, aD1Su, aD1Sv, aD2Su, aD2Sv, aD2SuvTemp);
1949     
1950     gp_Vec aVec(theP0, aPS);
1951     
1952     Standard_Real aSQDist = aVec.SquareMagnitude();
1953
1954     if(aSQDist >= aSQDistPrev)
1955       break;
1956
1957     aSQDistPrev = aSQDist;
1958     theU0 = aU;
1959     theV0 = aV;
1960     aNbIter--;
1961
1962     if(aSQDistPrev < aTol)
1963       break;
1964
1965     //Functions
1966     const Standard_Real aF1 = aD1Su.Dot(aVec), aF2 = aD1Sv.Dot(aVec);
1967
1968     //Derivatives
1969     const Standard_Real aDf1u = aD2Su.Dot(aVec) + aD1Su.Dot(aD1Su),
1970                         aDf1v = aD2Su.Dot(aD1Sv),
1971                         aDf2u = aDf1v,
1972                         aDf2v = aD2Sv.Dot(aVec) + aD1Sv.Dot(aD1Sv);
1973
1974     const Standard_Real aDet = aDf1u*aDf2v - aDf1v*aDf2u;
1975     aU -= theStep0U*(aDf2v*aF1 - aDf1v*aF2)/aDet;
1976     aV += theStep0V*(aDf2u*aF1 - aDf1u*aF2)/aDet;
1977   }
1978   while(aNbIter > 0);
1979
1980   return (aSQDistPrev < aTol);
1981 }
1982
1983 //=======================================================================
1984 //function : SeekPointOnBoundary
1985 //purpose  : 
1986 //=======================================================================
1987 Standard_Boolean IntWalk_PWalking::
1988   SeekPointOnBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
1989                       const Handle(Adaptor3d_HSurface)& theASurf2,
1990                       const Standard_Real theU1,
1991                       const Standard_Real theV1,
1992                       const Standard_Real theU2,
1993                       const Standard_Real theV2,
1994                       const Standard_Boolean isTheFirst)
1995 {
1996   const Standard_Real aTol = 1.0e-14;
1997   Standard_Boolean isOK = Standard_False;
1998   Standard_Real U1prec = theU1, V1prec = theV1, U2prec = theU2, V2prec = theV2;
1999
2000   Standard_Boolean flFinish = Standard_False;
2001
2002   Standard_Integer aNbIter = 20;
2003   while(!flFinish)
2004   {
2005     flFinish = Standard_False;
2006     Standard_Boolean aStatus = Standard_False;
2007
2008     do
2009     {
2010       aNbIter--;
2011       aStatus = DistanceMinimizeByGradient(theASurf1, theASurf2, U1prec, V1prec, U2prec, V2prec);
2012       if(aStatus)
2013       {
2014         break;
2015       }
2016
2017       aStatus = DistanceMinimizeByExtrema(theASurf1, theASurf2->Value(U2prec, V2prec), U1prec, V1prec);
2018       if(aStatus)
2019       {
2020         break;
2021       }
2022
2023       aStatus = DistanceMinimizeByExtrema(theASurf2, theASurf1->Value(U1prec, V1prec), U2prec, V2prec);
2024       if(aStatus)
2025       {
2026         break;
2027       }
2028     }
2029     while(!aStatus && (aNbIter > 0));
2030
2031     if(aStatus)
2032     {
2033       const Standard_Real aTolMax = 1.0e-8;
2034       Standard_Real aTolF = 0.0;
2035
2036       Standard_Real u1 = U1prec, v1 = V1prec, u2 = U2prec, v2 = V2prec;
2037
2038       flFinish = Checking(theASurf1, theASurf2, U1prec, V1prec, U2prec, V2prec, aTolF);
2039       
2040       if(aTolF <= aTolMax)
2041       {
2042         gp_Pnt  aP1 = theASurf1->Value(u1, v1),
2043                 aP2 = theASurf2->Value(u2, v2);
2044         gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
2045
2046         const Standard_Real aSQDist1 = aPInt.SquareDistance(aP1),
2047                             aSQDist2 = aPInt.SquareDistance(aP2);
2048         if((aSQDist1 < aTol) && (aSQDist2 < aTol))
2049         {
2050           IntSurf_PntOn2S anIP;
2051           anIP.SetValue(aPInt, u1, v1, u2, v2);
2052           
2053           if(isTheFirst)
2054             line->InsertBefore(1,anIP);
2055           else
2056             line->Add(anIP);
2057
2058           isOK = Standard_True;
2059         }
2060       }
2061     }
2062     else
2063     {
2064       break;
2065     }
2066
2067     if(aNbIter < 0)
2068       break;
2069   }
2070
2071   return isOK;
2072 }
2073
2074 //=======================================================================
2075 //function : PutToBoundary
2076 //purpose  : 
2077 //=======================================================================
2078 Standard_Boolean IntWalk_PWalking::
2079   PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
2080                 const Handle(Adaptor3d_HSurface)& theASurf2)
2081 {
2082   const Standard_Real aTolMin = Precision::Confusion();
2083
2084   Standard_Boolean hasBeenAdded = Standard_False;
2085
2086   const Standard_Real aU1bFirst = theASurf1->FirstUParameter();
2087   const Standard_Real aU1bLast = theASurf1->LastUParameter();
2088   const Standard_Real aU2bFirst = theASurf2->FirstUParameter();
2089   const Standard_Real aU2bLast = theASurf2->LastUParameter();
2090   const Standard_Real aV1bFirst = theASurf1->FirstVParameter();
2091   const Standard_Real aV1bLast = theASurf1->LastVParameter();
2092   const Standard_Real aV2bFirst = theASurf2->FirstVParameter();
2093   const Standard_Real aV2bLast = theASurf2->LastVParameter();
2094
2095   Standard_Real aTol = 1.0;
2096   aTol = Min(aTol, aU1bLast - aU1bFirst);
2097   aTol = Min(aTol, aU2bLast - aU2bFirst);
2098   aTol = Min(aTol, aV1bLast - aV1bFirst);
2099   aTol = Min(aTol, aV2bLast - aV2bFirst)*1.0e-3;
2100
2101   if(aTol <= 2.0*aTolMin)
2102     return hasBeenAdded;
2103
2104   Standard_Boolean isNeedAdding = Standard_False;
2105   Standard_Boolean isU1parallel = Standard_False, isV1parallel = Standard_False;
2106   Standard_Boolean isU2parallel = Standard_False, isV2parallel = Standard_False;
2107   IsParallel(line, Standard_True, aTol, isU1parallel, isV1parallel);
2108   IsParallel(line, Standard_False, aTol, isU2parallel, isV2parallel);
2109
2110   const Standard_Integer aNbPnts = line->NbPoints();
2111   Standard_Real u1, v1, u2, v2;
2112   line->Value(1).Parameters(u1, v1, u2, v2);
2113   Standard_Real aDelta = 0.0;
2114   
2115   if(!isV1parallel)
2116   {
2117     aDelta = u1 - aU1bFirst;
2118     if((aTolMin < aDelta) && (aDelta < aTol))
2119     {
2120       u1 = aU1bFirst - aDelta;
2121       isNeedAdding = Standard_True;
2122     }
2123     else
2124     {
2125       aDelta = aU1bLast - u1;
2126       if((aTolMin < aDelta) && (aDelta < aTol))
2127       {
2128         u1 = aU1bLast + aDelta;
2129         isNeedAdding = Standard_True;
2130       }
2131     }
2132   }
2133
2134   if(!isV2parallel)
2135   {
2136     aDelta = u2 - aU2bFirst;
2137     if((aTolMin < aDelta) && (aDelta < aTol))
2138     {
2139       u2 = aU2bFirst - aDelta;
2140       isNeedAdding = Standard_True;
2141     }
2142     else
2143     {
2144       aDelta = aU2bLast - u2;
2145       if((aTolMin < aDelta) && (aDelta < aTol))
2146       {
2147         u2 = aU2bLast + aDelta;
2148         isNeedAdding = Standard_True;
2149       }
2150     }
2151   }
2152
2153   if(!isU1parallel)
2154   {
2155     aDelta = v1 - aV1bFirst;
2156     if((aTolMin < aDelta) && (aDelta < aTol))
2157     {
2158       v1 = aV1bFirst - aDelta;
2159       isNeedAdding = Standard_True;
2160     }
2161     else
2162     {
2163       aDelta = aV1bLast - v1;
2164       if((aTolMin < aDelta) && (aDelta < aTol))
2165       {
2166         v1 = aV1bLast + aDelta;
2167         isNeedAdding = Standard_True;
2168       }
2169     }
2170   }
2171
2172   if(!isU2parallel)
2173   {
2174     aDelta = v2 - aV2bFirst;
2175     if((aTolMin < aDelta) && (aDelta < aTol))
2176     {
2177       v2 = aV2bFirst - aDelta;
2178       isNeedAdding = Standard_True;
2179     }
2180     else
2181     {
2182       aDelta = aV2bLast - v2;
2183       if((aTolMin < aDelta) && (aDelta < aTol))
2184       {
2185         v2 = aV2bLast + aDelta;
2186         isNeedAdding = Standard_True;
2187       }
2188     }
2189   }
2190
2191   if(isNeedAdding)
2192   {
2193     hasBeenAdded = 
2194       SeekPointOnBoundary(theASurf1, theASurf2, u1, 
2195                             v1, u2, v2, Standard_True);
2196   }
2197
2198   isNeedAdding = Standard_False;
2199   line->Value(aNbPnts).Parameters(u1, v1, u2, v2);
2200
2201   if(!isV1parallel)
2202   {
2203     aDelta = u1 - aU1bFirst;
2204     if((aTolMin < aDelta) && (aDelta < aTol))
2205     {
2206       u1 = aU1bFirst - aDelta;
2207       isNeedAdding = Standard_True;
2208     }
2209     else
2210     {
2211       aDelta = aU1bLast - u1;
2212       if((aTolMin < aDelta) && (aDelta < aTol))
2213       {
2214         u1 = aU1bLast + aDelta;
2215         isNeedAdding = Standard_True;
2216       }
2217     }
2218   }
2219
2220   if(!isV2parallel)
2221   {
2222     aDelta = u2 - aU2bFirst;
2223     if((aTolMin < aDelta) && (aDelta < aTol))
2224     {
2225       u2 = aU2bFirst - aDelta;
2226       isNeedAdding = Standard_True;
2227     }
2228     else
2229     {
2230       aDelta = aU2bLast - u2;
2231       if((aTolMin < aDelta) && (aDelta < aTol))
2232       {
2233         u2 = aU2bLast + aDelta;
2234         isNeedAdding = Standard_True;
2235       }
2236     }
2237   }
2238
2239   if(!isU1parallel)
2240   {
2241     aDelta = v1 - aV1bFirst;
2242     if((aTolMin < aDelta) && (aDelta < aTol))
2243     {
2244       v1 = aV1bFirst - aDelta;
2245       isNeedAdding = Standard_True;
2246     }
2247     else
2248     {
2249       aDelta = aV1bLast - v1;
2250       if((aTolMin < aDelta) && (aDelta < aTol))
2251       {
2252         v1 = aV1bLast + aDelta;
2253         isNeedAdding = Standard_True;
2254       }
2255     }
2256   }
2257
2258   if(!isU2parallel)
2259   {
2260     aDelta = v2 - aV2bFirst;
2261     if((aTolMin < aDelta) && (aDelta < aTol))
2262     {
2263       v2 = aV2bFirst - aDelta;
2264       isNeedAdding = Standard_True;
2265     }
2266     else
2267     {
2268       aDelta = aV2bLast - v2;
2269       if((aTolMin < aDelta) && (aDelta < aTol))
2270       {
2271         v2 = aV2bLast + aDelta;
2272         isNeedAdding = Standard_True;
2273       }
2274     }
2275   }
2276
2277   if(isNeedAdding)
2278   {
2279     hasBeenAdded = 
2280       SeekPointOnBoundary(theASurf1, theASurf2, u1, 
2281                             v1, u2, v2, Standard_False);
2282   }
2283
2284   return hasBeenAdded;
2285 }
2286
2287 //=======================================================================
2288 //function : SeekAdditionalPoints
2289 //purpose  : 
2290 //=======================================================================
2291 Standard_Boolean IntWalk_PWalking::
2292   SeekAdditionalPoints( const Handle(Adaptor3d_HSurface)& theASurf1,
2293                         const Handle(Adaptor3d_HSurface)& theASurf2,
2294                         const Standard_Integer theMinNbPoints)
2295 {
2296   const Standard_Real aTol = 1.0e-14;
2297   Standard_Integer aNbPoints = line->NbPoints();
2298   if(aNbPoints > theMinNbPoints)
2299     return Standard_True;
2300
2301   const Standard_Real aU1bFirst = theASurf1->FirstUParameter();
2302   const Standard_Real aU1bLast = theASurf1->LastUParameter();
2303   const Standard_Real aU2bFirst = theASurf2->FirstUParameter();
2304   const Standard_Real aU2bLast = theASurf2->LastUParameter();
2305   const Standard_Real aV1bFirst = theASurf1->FirstVParameter();
2306   const Standard_Real aV1bLast = theASurf1->LastVParameter();
2307   const Standard_Real aV2bFirst = theASurf2->FirstVParameter();
2308   const Standard_Real aV2bLast = theASurf2->LastVParameter();
2309
2310   
2311   Standard_Boolean isPrecise = Standard_False;
2312
2313   Standard_Real U1prec = 0.0, V1prec = 0.0, U2prec = 0.0, V2prec = 0.0;
2314
2315   Standard_Integer aNbPointsPrev = 0;
2316   while(aNbPoints < theMinNbPoints && (aNbPoints != aNbPointsPrev))
2317   {
2318     aNbPointsPrev = aNbPoints;
2319     for(Standard_Integer fp = 1, lp = 2; fp < aNbPoints; fp = lp + 1)
2320     {
2321       Standard_Real U1f, V1f, U2f, V2f; //first point in 1st and 2nd surafaces
2322       Standard_Real U1l, V1l, U2l, V2l; //last  point in 1st and 2nd surafaces
2323
2324       lp = fp+1;
2325       line->Value(fp).Parameters(U1f, V1f, U2f, V2f);
2326       line->Value(lp).Parameters(U1l, V1l, U2l, V2l);
2327
2328       U1prec = 0.5*(U1f+U1l);
2329       if(U1prec < aU1bFirst)
2330         U1prec = aU1bFirst;
2331       if(U1prec > aU1bLast)
2332         U1prec = aU1bLast;
2333
2334       V1prec = 0.5*(V1f+V1l);
2335       if(V1prec < aV1bFirst)
2336         V1prec = aV1bFirst;
2337       if(V1prec > aV1bLast)
2338         V1prec = aV1bLast;
2339
2340       U2prec = 0.5*(U2f+U2l);
2341       if(U2prec < aU2bFirst)
2342         U2prec = aU2bFirst;
2343       if(U2prec > aU2bLast)
2344         U2prec = aU2bLast;
2345
2346       V2prec = 0.5*(V2f+V2l);
2347       if(V2prec < aV2bFirst)
2348         V2prec = aV2bFirst;
2349       if(V2prec > aV2bLast)
2350         V2prec = aV2bLast;
2351
2352       Standard_Boolean aStatus = Standard_False;
2353       Standard_Integer aNbIter = 5;
2354       do
2355       {
2356         aStatus = DistanceMinimizeByGradient(theASurf1, theASurf2, U1prec, V1prec, U2prec, V2prec);
2357         if(aStatus)
2358         {
2359           break;
2360         }
2361
2362         aStatus = DistanceMinimizeByExtrema(theASurf1, theASurf2->Value(U2prec, V2prec), U1prec, V1prec);
2363         if(aStatus)
2364         {
2365           break;
2366         }
2367
2368         aStatus = DistanceMinimizeByExtrema(theASurf2, theASurf1->Value(U1prec, V1prec), U2prec, V2prec);
2369         if(aStatus)
2370         {
2371           break;
2372         }
2373       }
2374       while(!aStatus && (--aNbIter > 0));
2375
2376       if(aStatus)
2377       {
2378         gp_Pnt  aP1 = theASurf1->Value(U1prec, V1prec),
2379                 aP2 = theASurf2->Value(U2prec, V2prec);
2380         gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
2381
2382         const Standard_Real aSQDist1 = aPInt.SquareDistance(aP1),
2383                             aSQDist2 = aPInt.SquareDistance(aP2);
2384
2385         if((aSQDist1 < aTol) && (aSQDist2 < aTol))
2386         {
2387           IntSurf_PntOn2S anIP;
2388           anIP.SetValue(aPInt, U1prec, V1prec, U2prec, V2prec);
2389           line->InsertBefore(lp, anIP);
2390           
2391           isPrecise = Standard_True;
2392
2393           if(++aNbPoints >= theMinNbPoints)
2394             break;
2395         }
2396         else
2397         {
2398           lp--;
2399         }
2400       }
2401     }
2402   }
2403
2404   return isPrecise;
2405 }
2406
2407