0026788: Compiler warnings when OCCT_DEBUG is enabled
[occt.git] / src / Blend / Blend_Walking_4.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 #include <gce_MakePln.hxx>
16 #include <Extrema_ExtPS.hxx>
17 #include <Extrema_ExtPC.hxx>
18
19 static const Standard_Real CosRef3D = 0.88;
20
21 static void RecadreIfPeriodic(Standard_Real& NewU,
22                               Standard_Real& NewV,
23                               const Standard_Real OldU,
24                               const Standard_Real OldV,
25                               const Standard_Real UPeriod,
26                               const Standard_Real VPeriod)
27 {
28   if (UPeriod > 0.)
29   {
30     Standard_Real sign = (NewU < OldU)? 1 : -1;
31     while (Abs(NewU - OldU) > UPeriod/2)
32       NewU += sign * UPeriod;
33   }
34   if (VPeriod > 0.)
35   {
36     Standard_Real sign = (NewV < OldV)? 1 : -1;
37     while (Abs(NewV - OldV) > VPeriod/2)
38       NewV += sign * VPeriod;
39   }
40 }
41
42 static void evalpinit(math_Vector& parinit,
43                       const Blend_Point& previousP,
44                       const Standard_Real parprec,
45                       const Standard_Real param,
46                       const math_Vector& infbound,
47                       const math_Vector& supbound,
48                       const Standard_Boolean classonS1, 
49                       const Standard_Boolean classonS2)
50 {
51   if(previousP.IsTangencyPoint()){
52     previousP.ParametersOnS1(parinit(1),parinit(2));
53     previousP.ParametersOnS2(parinit(3),parinit(4));
54   }
55   else {
56     Standard_Real u1,v1,u2,v2;
57     Standard_Real du1,dv1,du2,dv2;
58     Standard_Boolean Inside=Standard_True;
59     previousP.ParametersOnS1(u1,v1);
60     previousP.ParametersOnS2(u2,v2);
61     previousP.Tangent2dOnS1().Coord(du1,dv1);
62     previousP.Tangent2dOnS2().Coord(du2,dv2);
63     Standard_Real step = param - parprec;
64     u1+= step*du1;
65     v1+= step*dv1;
66     if ( classonS1 ) {
67       if ((u1<infbound(1)) || (u1>supbound(1))) Inside=Standard_False;
68       if ((v1<infbound(2)) || (v1>supbound(2))) Inside=Standard_False;
69     }
70     u2+= step*du2;
71     v2+= step*dv2;
72     if ( classonS2) {
73       if ((u2<infbound(3)) || (u2>supbound(3))) Inside=Standard_False;
74       if ((v2<infbound(4)) || (v2>supbound(4))) Inside=Standard_False;
75     }
76
77     if (Inside) {
78       parinit(1) = u1;
79       parinit(2) = v1;
80       parinit(3) = u2;
81       parinit(4) = v2;
82     }
83     else { // on ne joue pas au plus malin
84       previousP.ParametersOnS1(parinit(1),parinit(2));
85       previousP.ParametersOnS2(parinit(3),parinit(4));
86     }
87     
88   }
89 }
90
91
92
93 void Blend_Walking::InternalPerform(Blend_Function& Func,
94                                     Blend_FuncInv& FuncInv,
95                                     const Standard_Real Bound)
96 {
97   Standard_Real Cosi = 0., Cosi2 = 0.;
98
99   Standard_Real stepw = pasmax;
100   Standard_Integer nbp = line->NbPoints();
101   if(nbp >= 2){ //On reprend le dernier step s'il n est pas trop petit.
102     if(sens < 0.){
103       stepw = (line->Point(2).Parameter() - line->Point(1).Parameter());
104     }
105     else{
106       stepw = (line->Point(nbp).Parameter() - line->Point(nbp - 1).Parameter());
107     }
108     stepw = Max(stepw,100.*tolgui);
109   }
110   Standard_Real parprec = param;
111   gp_Vec TgOnGuide, PrevTgOnGuide;
112   gp_Pnt PtOnGuide;
113   hguide->D1(parprec, PtOnGuide, TgOnGuide);
114   PrevTgOnGuide = TgOnGuide;
115
116   if (sens*(parprec - Bound) >= -tolgui) {
117     return;
118   }
119   Blend_Status State = Blend_OnRst12;
120   TopAbs_State situ1 =TopAbs_IN,situ2=TopAbs_IN;
121   Standard_Real w1,w2;
122   Standard_Integer Index1 = 0, Index2 = 0, nbarc;
123   Standard_Boolean Arrive,recad1,recad2, control;
124   Standard_Boolean Isvtx1 = Standard_False, Isvtx2 = Standard_False, echecrecad;
125   gp_Pnt2d p2d;
126   math_Vector tolerance(1,4),infbound(1,4),supbound(1,4),parinit(1,4);
127   math_Vector solrst1(1,4),solrst2(1,4);
128   TheVertex Vtx1,Vtx2;
129   TheExtremity Ext1,Ext2;
130
131   //IntSurf_Transition Tline,Tarc;
132
133   Func.GetTolerance(tolerance,tolesp);
134   Func.GetBounds(infbound,supbound);
135
136   math_FunctionSetRoot rsnld(Func,tolerance,30);
137   parinit = sol;
138
139   Arrive = Standard_False;
140   param = parprec + sens*stepw;
141   if(sens *(param - Bound) > 0.) {
142     stepw = sens*(Bound - parprec)*0.5;
143     param = parprec + sens*stepw;
144   }
145
146   evalpinit(parinit,previousP,parprec,param,
147             infbound,supbound, clasonS1, clasonS2);
148
149   while (!Arrive) {
150
151 #ifdef OCCT_DEBUG
152     sectioncalculee = 0;
153     nbcomputedsection++;
154 #endif
155
156     hguide->D1(param, PtOnGuide, TgOnGuide);
157     //Check deflection on guide
158     Cosi = PrevTgOnGuide * TgOnGuide;
159     if (Cosi < gp::Resolution()) //angle>=pi/2 or null magnitude
160       Cosi2 = 0.;
161     else
162       Cosi2 = Cosi * Cosi / PrevTgOnGuide.SquareMagnitude() / TgOnGuide.SquareMagnitude();
163     if (Cosi2 < CosRef3D) //angle 3d too great
164     {
165       State = Blend_StepTooLarge;
166       stepw = stepw/2.;
167       param = parprec + sens*stepw;  // on ne risque pas de depasser Bound.
168       if (Abs(stepw) < tolgui) {
169         Ext1.SetValue(previousP.PointOnS1(),
170                       sol(1),sol(2),
171                       previousP.Parameter(),tolesp);
172         Ext2.SetValue(previousP.PointOnS2(),
173                       sol(3),sol(4),
174                       previousP.Parameter(),tolesp);
175         if (!previousP.IsTangencyPoint()) {
176           Ext1.SetTangent(previousP.TangentOnS1());
177           Ext2.SetTangent(previousP.TangentOnS2());
178         }
179         Arrive = Standard_True;
180       }
181       continue;
182     }
183     PrevTgOnGuide = TgOnGuide;
184     //////////////////////////
185     
186     Standard_Boolean bonpoint = 1;
187     Func.Set(param);
188     rsnld.Perform(Func,parinit,infbound,supbound);
189
190     if (!rsnld.IsDone()) {
191       State = Blend_StepTooLarge;
192       bonpoint = 0;
193     }
194     else {
195       rsnld.Root(sol);
196
197       if(clasonS1) situ1 = domain1->Classify(gp_Pnt2d(sol(1),sol(2)),
198                                              Min(tolerance(1),tolerance(2)),0);
199       else situ1 = TopAbs_IN;
200       if(clasonS2) situ2 = domain2->Classify(gp_Pnt2d(sol(3),sol(4)),
201                                              Min(tolerance(3),tolerance(4)),0);
202       else situ2 = TopAbs_IN;
203     }
204     if(bonpoint && line->NbPoints() == 1 && (situ1 != TopAbs_IN || situ2 != TopAbs_IN)){
205       State = Blend_StepTooLarge;
206       bonpoint = 0;
207     }
208     if(bonpoint){
209       w1 = w2 = Bound;
210       recad1 = Standard_False;
211       recad2 = Standard_False;
212       echecrecad = Standard_False;
213       control = Standard_False;
214
215       if (situ1 == TopAbs_OUT || situ1 == TopAbs_ON) {
216         // pb inverse sur surf1
217         //Si le recadrage s'effectue dans le sens de la progression a une tolerance pres,
218         //on a pris la mauvaise solution.
219         recad1 = Recadre(FuncInv,Standard_True,
220                          sol,solrst1,Index1,Isvtx1,Vtx1);
221
222         if (recad1) {
223           Standard_Real wtemp;
224           wtemp  = solrst1(2);
225           if ((param - wtemp)/sens>= -10*tolesp){
226             w1 = solrst1(2);
227             control = Standard_True;
228           }
229           else {
230             echecrecad = Standard_True;
231             recad1 = Standard_False;
232             State = Blend_StepTooLarge;
233             bonpoint = 0;
234             stepw = stepw/2.;
235           }
236         }
237         else {
238           echecrecad = Standard_True;
239         }
240       }
241       if (situ2 == TopAbs_OUT || situ2 == TopAbs_ON) {
242         // pb inverse sur surf2
243         //Si le recadrage s'effectue dans le sens de la progression a une tolerance pres,
244         //on a pris la mauvaise solution.
245         recad2 = Recadre(FuncInv,Standard_False,
246                          sol,solrst2,Index2,Isvtx2,Vtx2);
247         
248         if (recad2) {
249           Standard_Real wtemp;
250           wtemp = solrst2(2);
251           if ((param - wtemp)/sens>= -10*tolesp){
252             w2 = solrst2(2);
253             control = Standard_True;
254           }
255           else {
256             echecrecad = Standard_True;
257             recad2 = Standard_False;
258             State = Blend_StepTooLarge;
259             bonpoint = 0;
260             stepw = stepw/2.;
261           }
262         }
263         else {
264           echecrecad = Standard_True;
265         }
266       }
267       
268       // Que faut il controler
269       if (recad1 && recad2) {
270           if (Abs(w1-w2) <= 10*tolgui) {
271           // pas besoin de controler les recadrage
272           // Le control pouvant se planter (cf model blend10)
273           // La tolerance est choisie grossse afin, de permetre au 
274           // cheminement suivant, de poser quelques sections ...
275           control = Standard_False; 
276           }
277           else if (sens*(w1-w2) < 0.) {
278             //sol sur 1 ?
279             recad2 = Standard_False;
280           }
281           else {
282             //sol sur 2 ?
283             recad1 = Standard_False;
284           }
285         }
286
287       // Controle effectif des recadrage
288       if (control) {
289         TopAbs_State situ;
290         if (recad1 && clasonS2) {
291           situ = recdomain2->Classify(gp_Pnt2d(solrst1(3),solrst1(4)),
292                                       Min(tolerance(3),tolerance(4)));
293           if (situ == TopAbs_OUT) {
294             recad1 = Standard_False;
295             echecrecad = Standard_True;
296           }
297         }
298         else if (recad2 && clasonS1) {
299           situ = recdomain1->Classify(gp_Pnt2d(solrst2(3),solrst2(4)),
300                                       Min(tolerance(1),tolerance(1)));
301           if (situ == TopAbs_OUT) {
302             recad2 = Standard_False;
303             echecrecad = Standard_True;
304           }
305         }
306       }
307
308       if(recad1 || recad2) echecrecad = Standard_False;
309
310       if (!echecrecad) {
311         if (recad1 && recad2) {
312           //sol sur 1 et 2 a la fois
313           // On passe par les arcs , pour ne pas avoir de probleme
314           // avec les surfaces periodiques.
315           State = Blend_OnRst12;
316           param =  (w1+w2)/2;
317           gp_Pnt Pnt1, Pnt2;
318           p2d = TheArcTool::Value(recdomain1->Value(),solrst1(1));
319           sol(1) = p2d.X();
320           sol(2) = p2d.Y();
321           Pnt1 = TheSurfaceTool::Value(surf1,sol(1),sol(2));
322           p2d = TheArcTool::Value(recdomain2->Value(),solrst2(1));
323           sol(3) = p2d.X();
324           sol(4) = p2d.Y();
325           Pnt2 = TheSurfaceTool::Value(surf2,sol(3),sol(4));
326           const Standard_Real TolProd = 1.e-5;
327           Standard_Real SavedParams [2];
328           Standard_Boolean SameDirs [2] = {Standard_False, Standard_False};
329           ChFiDS_ElSpine& theElSpine = hguide->ChangeCurve();
330           SavedParams[0] = theElSpine.GetSavedFirstParameter();
331           SavedParams[1] = theElSpine.GetSavedLastParameter();
332           for (Standard_Integer ind = 0; ind < 2; ind++)
333           {
334             if (!Precision::IsInfinite(SavedParams[ind]))
335             {
336               //Check the original first and last parameters of guide curve
337               //for equality to found parameter <param>:
338               //check equality of tangent to guide curve and
339               //normal to plane built on 3 points:
340               //point on guide curve and points on restrictions of adjacent
341               //surfaces.
342               gp_Pnt Pnt0;
343               gp_Vec Dir0;
344               hguide->D1(SavedParams[ind], Pnt0, Dir0);
345               Standard_Real Length = Dir0.Magnitude();
346               if (Length <= gp::Resolution())
347                 continue;
348               Dir0 /= Length;
349               gce_MakePln PlaneBuilder(Pnt0, Pnt1, Pnt2);
350               if (!PlaneBuilder.IsDone())
351                 continue;
352               gp_Pln thePlane = PlaneBuilder.Value();
353               gp_Dir DirPlane = thePlane.Axis().Direction();
354               gp_Vec theProd = Dir0 ^ DirPlane;
355               Standard_Real ProdMod = theProd.Magnitude();
356               if (ProdMod <= TolProd)
357                 SameDirs[ind] = Standard_True;
358             }
359           }
360           Standard_Real theParam = Precision::Infinite();
361           //Choose the closest parameter
362           if (SameDirs[0] && SameDirs[1])
363             theParam = (Abs(param - SavedParams[0]) < Abs(param - SavedParams[1]))?
364               SavedParams[0] : SavedParams[1];
365           else if (SameDirs[0])
366             theParam = SavedParams[0];
367           else if (SameDirs[1])
368             theParam = SavedParams[1];
369
370           Standard_Real NewU, NewV, NewParam;
371           gp_Pnt NewPnt;
372           Standard_Boolean Corrected = CorrectExtremityOnOneRst(1, sol(3), sol(4), param, Pnt1,
373                                                                 NewU, NewV, NewPnt, NewParam);
374           if (Corrected)
375           {
376             if (Abs(param - NewParam) < Abs(param - theParam))
377               theParam = NewParam;
378           }
379           
380           if (!Precision::IsInfinite(theParam))
381             param = theParam;
382         }
383         else if (recad1) {
384           // sol sur 1
385           State = Blend_OnRst1;
386           param = w1;
387           recdomain1->Init();
388           nbarc = 1;
389           while (nbarc < Index1) {
390             nbarc++;
391             recdomain1->Next();
392           }
393           p2d = TheArcTool::Value(recdomain1->Value(),solrst1(1));
394           sol(1) = p2d.X();
395           sol(2) = p2d.Y();
396           sol(3) = solrst1(3);
397           sol(4) = solrst1(4);
398           gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf1,sol(1),sol(2));
399           Standard_Real NewU, NewV, NewParam;
400           gp_Pnt NewPnt;
401           Standard_Boolean Corrected = CorrectExtremityOnOneRst(1, sol(3), sol(4), param, thePntOnRst,
402                                                                 NewU, NewV, NewPnt, NewParam);
403           if (Corrected)
404           {
405             param = NewParam;
406             sol(3) = NewU;
407             sol(4) = NewV;
408           }
409         }
410         else if (recad2) {
411           //sol sur 2
412           State = Blend_OnRst2;
413           param = w2;
414           
415           recdomain2->Init();
416           nbarc = 1;
417           while (nbarc < Index2) {
418             nbarc++;
419             recdomain2->Next();
420           }
421           p2d = TheArcTool::Value(recdomain2->Value(),solrst2(1));
422           sol(1) = solrst2(3);
423           sol(2) = solrst2(4);
424           sol(3) = p2d.X();
425           sol(4) = p2d.Y();
426           gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf2,sol(3),sol(4));
427           Standard_Real NewU, NewV, NewParam;
428           gp_Pnt NewPnt;
429           Standard_Boolean Corrected = CorrectExtremityOnOneRst(2, sol(1), sol(2), param, thePntOnRst,
430                                                                 NewU, NewV, NewPnt, NewParam);
431           if (Corrected)
432           {
433             param = NewParam;
434             sol(1) = NewU;
435             sol(2) = NewV;
436           }
437         }
438         else {
439           State = Blend_OK;
440         }
441
442         Standard_Boolean testdefl = 1;
443 #ifdef OCCT_DEBUG
444         testdefl = !Blend_GetcontextNOTESTDEFL();
445 #endif  
446         if (recad1 || recad2) {
447           Func.Set(param);
448           // Il vaut mieux un pas non orthodoxe que pas de recadrage!! PMN
449           State = TestArret(Func, State, 
450                             (testdefl && (Abs(stepw) > 3*tolgui)),
451                             Standard_False, Standard_True);
452         }
453         else {
454           State = TestArret(Func, State, testdefl);
455         }
456       }
457       else { 
458         // Ou bien le pas max est mal regle. On divise.
459 //      if(line->NbPoints() == 1) State = Blend_StepTooLarge;
460         if (stepw > 2*tolgui) State = Blend_StepTooLarge;
461         // Sinon echec recadrage. On sort avec PointsConfondus
462         else {
463 #ifdef OCCT_DEBUG
464           cout << "Echec recadrage" << endl;
465 #endif    
466           State = Blend_SamePoints;
467         }
468       }
469     }
470
471 #ifdef OCCT_DEBUG
472     if (Blend_GettraceDRAWSECT()){
473       Drawsect(surf1,surf2,sol,param,Func, State);
474     }
475 #endif
476     switch (State) {
477     case Blend_OK :
478       {  
479         // Mettre a jour la ligne.
480         if (sens>0.) {
481           line->Append(previousP);
482         }
483         else {
484           line->Prepend(previousP);
485         }
486
487         parprec = param;
488
489         if (param == Bound) {
490           Arrive = Standard_True;
491           Ext1.SetValue(previousP.PointOnS1(),
492                         sol(1),sol(2),
493                         previousP.Parameter(), tolesp);
494           Ext2.SetValue(previousP.PointOnS2(),
495                         sol(3),sol(4),
496                         previousP.Parameter(), tolesp);
497           if (!previousP.IsTangencyPoint()) {
498             Ext1.SetTangent(previousP.TangentOnS1());
499             Ext2.SetTangent(previousP.TangentOnS2());
500           }
501
502           // Indiquer que fin sur Bound.
503         }
504         else {
505           param = param + sens*stepw;
506           if (sens*(param - Bound) > - tolgui) {
507             param = Bound;
508           }
509         }
510         evalpinit(parinit,previousP,parprec,param,
511                   infbound,supbound, clasonS1, clasonS2);
512       }
513       break;
514       
515     case Blend_StepTooLarge :
516       {
517         stepw = stepw/2.;
518         if (Abs(stepw) < tolgui) {
519           Ext1.SetValue(previousP.PointOnS1(),
520                         sol(1),sol(2),
521                         previousP.Parameter(),tolesp);
522           Ext2.SetValue(previousP.PointOnS2(),
523                         sol(3),sol(4),
524                         previousP.Parameter(),tolesp);
525           if (!previousP.IsTangencyPoint()) {
526             Ext1.SetTangent(previousP.TangentOnS1());
527             Ext2.SetTangent(previousP.TangentOnS2());
528           }
529           Arrive = Standard_True;
530           if (line->NbPoints()>=2) {
531             // Indiquer qu on s arrete en cours de cheminement
532           }
533 //        else {
534 //          line->Clear();
535 //        }
536         }
537         else {
538           param = parprec + sens*stepw;  // on ne risque pas de depasser Bound.
539           evalpinit(parinit,previousP,parprec,param,
540                     infbound,supbound, clasonS1, clasonS2);
541         }
542       }
543       break;
544       
545     case Blend_StepTooSmall :
546       {
547         // Mettre a jour la ligne.
548         if (sens>0.) {
549           line->Append(previousP);
550         }
551         else {
552           line->Prepend(previousP);
553         }
554
555         parprec = param;
556
557         stepw = Min(1.5*stepw,pasmax);
558         if (param == Bound) {
559           Arrive = Standard_True;
560           Ext1.SetValue(previousP.PointOnS1(),
561                         sol(1),sol(2),
562                         previousP.Parameter(),tolesp);
563           Ext2.SetValue(previousP.PointOnS2(),
564                         sol(3),sol(4), 
565                         previousP.Parameter(),tolesp);
566           if (!previousP.IsTangencyPoint()) {
567             Ext1.SetTangent(previousP.TangentOnS1());
568             Ext2.SetTangent(previousP.TangentOnS2());
569           }
570           // Indiquer que fin sur Bound.
571         }
572         else {
573           param = param + sens*stepw;
574           if (sens*(param - Bound) > - tolgui) {
575             param = Bound;
576           }
577         }
578         evalpinit(parinit,previousP,parprec,param,
579                   infbound,supbound, clasonS1, clasonS2);
580       }
581       break;
582       
583     case Blend_OnRst1  :
584       {
585         if (sens>0.) {
586           line->Append(previousP);
587         }
588         else {
589           line->Prepend(previousP);
590         }
591         MakeExtremity(Ext1,Standard_True,Index1,
592                       solrst1(1),Isvtx1,Vtx1);
593         // On blinde le cas singulier ou un des recadrage a planter
594         if (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2*tolesp)) {
595           Ext2.SetValue(previousP.PointOnS1(),
596                         sol(3),sol(4),tolesp);
597           if (Isvtx1) MakeSingularExtremity(Ext2, Standard_False, Vtx1);
598         }
599         else {
600           Ext2.SetValue(previousP.PointOnS2(),
601                         sol(3),sol(4),
602                         previousP.Parameter(),tolesp);
603         }
604         Arrive = Standard_True;
605       }
606       break;
607
608     case Blend_OnRst2  :
609       {
610         if (sens>0.) {
611           line->Append(previousP);
612         }
613         else {
614           line->Prepend(previousP);
615         }
616         // On blinde le cas singulier ou un des recadrage a plante
617         if (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2*tolesp)) {
618           Ext1.SetValue(previousP.PointOnS2(),
619                         sol(1),sol(2),tolesp);
620           if (Isvtx2) MakeSingularExtremity(Ext1, Standard_True, Vtx2);
621         }
622         else {
623           Ext1.SetValue(previousP.PointOnS1(),
624                         sol(1),sol(2),
625                         previousP.Parameter(),tolesp);
626         }
627         MakeExtremity(Ext2,Standard_False,Index2,
628                       solrst2(1),Isvtx2,Vtx2);
629         Arrive = Standard_True;
630       }
631       break;
632
633
634     case Blend_OnRst12 :
635       {
636         if (sens>0.) {
637           line->Append(previousP);
638         }
639         else {
640           line->Prepend(previousP);
641         }
642
643         if ( (Isvtx1 != Isvtx2) &&
644             (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2*tolesp)) ) {
645           // On blinde le cas singulier ou un seul recadrage
646           // est reconnu comme vertex.
647           if (Isvtx1) {
648             Isvtx2 = Standard_True;
649             Vtx2 = Vtx1;
650           }
651           else {
652             Isvtx1 = Standard_True;
653             Vtx1 = Vtx2;
654           }
655         }
656
657         MakeExtremity(Ext1,Standard_True,Index1,
658                       solrst1(1),Isvtx1,Vtx1);
659         MakeExtremity(Ext2,Standard_False,Index2,
660                       solrst2(1),Isvtx2,Vtx2);
661         Arrive = Standard_True;
662       }
663       break;
664
665     case Blend_SamePoints :
666       {
667         // On arrete
668 #ifdef OCCT_DEBUG
669         cout << " Points confondus dans le cheminement" << endl;
670 #endif
671         Ext1.SetValue(previousP.PointOnS1(),
672                       sol(1),sol(2),
673                       previousP.Parameter(),tolesp);
674         Ext2.SetValue(previousP.PointOnS2(),
675                       sol(3),sol(4),
676                       previousP.Parameter(),tolesp);;
677         if (!previousP.IsTangencyPoint()) {
678           Ext1.SetTangent(previousP.TangentOnS1());
679           Ext2.SetTangent(previousP.TangentOnS2());
680         }
681         Arrive = Standard_True;
682       }
683       break;
684     default:
685       break;
686     }
687     if (Arrive) {
688       if (sens > 0.) {
689         line->SetEndPoints(Ext1,Ext2);
690       }
691       else {
692         line->SetStartPoints(Ext1,Ext2);
693
694       }
695     }
696
697   }
698
699 }
700
701 Standard_Boolean Blend_Walking::CorrectExtremityOnOneRst(const Standard_Integer IndexOfRst,
702                                                          const Standard_Real theU,
703                                                          const Standard_Real theV,
704                                                          const Standard_Real theParam,
705                                                          const gp_Pnt& thePntOnRst,
706                                                          Standard_Real& NewU,
707                                                          Standard_Real& NewV,
708                                                          gp_Pnt& NewPoint,
709                                                          Standard_Real& NewParam) const
710 {
711   const Standard_Real TolAng = 0.001; //bug OCC25701
712   
713   ChFiDS_ElSpine& theElSpine = hguide->ChangeCurve();
714   if (theElSpine.NbVertices() == 0)
715     return Standard_False;
716   
717   Handle(TheTopolTool) DomainOfRst = (IndexOfRst == 1)? recdomain1 : recdomain2;
718   TheSurface SurfOfRst = (IndexOfRst == 1)? surf1 : surf2;
719   TheSurface AnotherSurf = (IndexOfRst == 1)? surf2 : surf1;
720   
721   //Correct point on surface 2
722   //First we find right <param>
723   Standard_Real Ends [2];
724   Ends[0] = TheArcTool::FirstParameter(DomainOfRst->Value());
725   Ends[1] = TheArcTool::LastParameter(DomainOfRst->Value());
726   Standard_Real GlobalMinSqDist = Precision::Infinite();
727   Standard_Real ParamOnGuide = 0;
728   gp_Pnt PointOnGuide;
729   for (Standard_Integer k = 0; k < 2; k++)
730   {
731     gp_Pnt2d P2dOnEnd = TheArcTool::Value(DomainOfRst->Value(), Ends[k]);
732     gp_Pnt PntOnEnd = TheSurfaceTool::Value(SurfOfRst, P2dOnEnd.X(), P2dOnEnd.Y());
733     Extrema_ExtPC projoncurv(PntOnEnd, theElSpine);
734     if (!projoncurv.IsDone())
735       continue;
736     Standard_Real MinSqDist = Precision::Infinite();
737     Standard_Integer imin = 0;
738     for (Standard_Integer ind = 1; ind <= projoncurv.NbExt(); ind++)
739     {
740       Standard_Real aSqDist = projoncurv.SquareDistance(ind);
741       if (aSqDist < MinSqDist)
742       {
743         MinSqDist = aSqDist;
744         imin = ind;
745       }
746     }
747     if (MinSqDist < GlobalMinSqDist)
748     {
749       GlobalMinSqDist = MinSqDist;
750       ParamOnGuide = projoncurv.Point(imin).Parameter();
751       PointOnGuide = projoncurv.Point(imin).Value();
752     }
753   }
754   NewParam = ParamOnGuide;
755   if (hguide->IsPeriodic())
756   {
757     Standard_Real Period = hguide->Period();
758     Standard_Real sign = (NewParam < theParam)? 1 : -1;
759     while (Abs(NewParam - theParam) > Period/2)
760       NewParam += sign *Period;
761   }
762
763   //Second we find right point and tangent on guide
764   GlobalMinSqDist = Precision::Infinite();
765   gp_Ax1 theAx1;
766   for (Standard_Integer ind = 1; ind <= theElSpine.NbVertices(); ind++)
767   {
768     const gp_Ax1& anAx1 = theElSpine.VertexWithTangent(ind);
769     gp_Pnt aPnt = anAx1.Location();
770     Standard_Real aSqDist = PointOnGuide.SquareDistance(aPnt);
771     if (aSqDist < GlobalMinSqDist)
772     {
773       GlobalMinSqDist = aSqDist;
774       theAx1 = anAx1;
775     }
776   }
777   const gp_Pnt& Pnt0 = theAx1.Location();
778   const gp_Dir& Dir0 = theAx1.Direction();
779   //Check new point: is it real solution?
780   gp_Pnt OldPonGuide = hguide->Value(theParam);
781   gp_Pnt PntOnSurf2 = TheSurfaceTool::Value(AnotherSurf,theU,theV); //old point
782   gce_MakePln PlaneBuilder(thePntOnRst, OldPonGuide, PntOnSurf2);
783   if (!PlaneBuilder.IsDone())
784     return Standard_False;
785   gp_Pln OldPlane = PlaneBuilder.Value();
786   gp_Dir OldDir = OldPlane.Axis().Direction();
787   Standard_Real Angle = OldDir.Angle(Dir0);
788   if (Angle > M_PI/2)
789     Angle = M_PI - Angle;
790   if (Angle > TolAng)
791     return Standard_False;
792   ///////////////////////////////////////
793   //Project the point(theU,theV) on the plane(Pnt0,Dir0)
794   gp_Vec aVec(Pnt0, PntOnSurf2);
795   gp_Vec aTranslation( (aVec.XYZ() * Dir0.XYZ()) * Dir0.XYZ() );
796   gp_Pnt PntOnPlane = PntOnSurf2.Translated(-aTranslation);
797
798   //Check new point again: does point on restriction belong to the plane?
799   PlaneBuilder = gce_MakePln(thePntOnRst, Pnt0, PntOnPlane);
800   if (!PlaneBuilder.IsDone())
801     return Standard_False;
802   gp_Pln NewPlane = PlaneBuilder.Value();
803   const gp_Dir& DirOfNewPlane = NewPlane.Axis().Direction();
804   Angle = Dir0.Angle(DirOfNewPlane);
805   if (Angle > M_PI/2)
806     Angle = M_PI - Angle;
807   if (Angle > TolAng)
808     return Standard_False;
809   ////////////////////////////////////////////////////////////////////////
810   
811   //Project the point <PntOnPlane> on the surface 2
812   Extrema_ExtPS projonsurf(PntOnPlane, AnotherSurf->Surface(),
813                            Precision::PConfusion(), Precision::PConfusion(),
814                            Extrema_ExtFlag_MIN);
815   if (projonsurf.IsDone())
816   {
817     Standard_Real MinSqDist = Precision::Infinite();
818     Standard_Integer imin = 0;
819     for (Standard_Integer ind = 1; ind <= projonsurf.NbExt(); ind++)
820     {
821       Standard_Real aSqDist = projonsurf.SquareDistance(ind);
822       if (aSqDist < MinSqDist)
823       {
824         MinSqDist = aSqDist;
825         imin = ind;
826       }
827     }
828     if (imin)
829     {
830       Extrema_POnSurf NewPOnSurf2 = projonsurf.Point(imin);
831       NewPoint = NewPOnSurf2.Value();
832       NewPOnSurf2.Parameter(NewU, NewV);
833       Standard_Real uperiod = (AnotherSurf->IsUPeriodic())? AnotherSurf->UPeriod() : 0.;
834       Standard_Real vperiod = (AnotherSurf->IsVPeriodic())? AnotherSurf->VPeriod() : 0.;
835       RecadreIfPeriodic(NewU, NewV, theU, theV,
836                         uperiod, vperiod);
837       return Standard_True;
838     }
839   }
840
841   return Standard_False;
842 }