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