0024428: Implementation of LGPL license
[occt.git] / src / BRepBlend / BRepBlend_SurfRstLineBuilder.cxx
1 // Created on: 1997-01-24
2 // Created by: Laurent BOURESCHE
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and / or modify it
9 // under the terms of the GNU Lesser General Public version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <stdio.h>
18
19 #include <BRepBlend_SurfRstLineBuilder.ixx>
20 #include <BRepBlend_BlendTool.hxx>
21 #include <TopAbs.hxx>
22 #include <IntSurf.hxx>
23 #include <math_FunctionSetRoot.hxx>
24 #include <gp_Pnt2d.hxx>
25 #include <gp_Pnt.hxx>
26 #include <gp_Vec2d.hxx>
27 #include <gp_Vec.hxx>
28
29 #ifdef DEB
30 #include <TColStd_Array1OfInteger.hxx>
31 #include <TColStd_Array1OfReal.hxx>
32 #include <TColgp_Array1OfPnt2d.hxx>
33 #include <TColgp_Array1OfVec.hxx>
34 #include <TColgp_Array1OfVec2d.hxx>
35 #include <TColgp_Array1OfPnt.hxx>
36 #include <Geom_BSplineCurve.hxx>
37 #ifdef DRAW
38 #include <DrawTrSurf.hxx>
39 #endif
40 static Standard_Integer IndexOfSection = 0;
41 extern Standard_Boolean Blend_GettraceDRAWSECT(); 
42 #ifdef DEB_BBPP_N_TRDERIV
43 // for debug : visualisation of the section
44 static Standard_Boolean BBPP(const Standard_Real param,
45                              Blend_SurfRstFunction& Func,
46                              const math_Vector& sol,
47                              const Standard_Real tol,
48                              Blend_Point& BP)
49 {
50   if(!Func.IsSolution(sol,tol)) return 0;
51   gp_Pnt pnts = Func.PointOnS();
52   gp_Pnt pntrst = Func.PointOnRst();
53   gp_Pnt2d p2ds = Func.Pnt2dOnS();
54   gp_Pnt2d p2drst = Func.Pnt2dOnRst();
55   Standard_Real w = Func.ParameterOnRst();
56   BP = Blend_Point(pnts,pntrst,param,
57                    p2ds.X(),p2ds.Y(),
58                    p2drst.X(),p2drst.Y(),w);
59   return 1;
60 }
61 static void tracederiv(Blend_SurfRstFunction& Func,
62                        const Blend_Point& BP1,
63                        const Blend_Point& BP2)
64 {
65   Standard_Integer hp,hk,hd,hp2d,i;
66   Func.GetShape(hp,hk,hd,hp2d);
67   TColgp_Array1OfPnt TP1(1,hp);
68   TColgp_Array1OfVec TDP1(1,hp);
69   TColgp_Array1OfPnt2d TP2d1(1,hp2d);
70   TColgp_Array1OfVec2d TDP2d1(1,hp2d);
71   TColStd_Array1OfReal TW1(1,hp);
72   TColStd_Array1OfReal TDW1(1,hp);
73   Func.Section(BP1,TP1,TDP1,TP2d1,TDP2d1,TW1,TDW1);
74
75   TColgp_Array1OfPnt TP2(1,hp);
76   TColgp_Array1OfVec TDP2(1,hp);
77   TColgp_Array1OfPnt2d TP2d2(1,hp2d);
78   TColgp_Array1OfVec2d TDP2d2(1,hp2d);
79   TColStd_Array1OfReal TW2(1,hp);
80   TColStd_Array1OfReal TDW2(1,hp);
81   Func.Section(BP2,TP2,TDP2,TP2d2,TDP2d2,TW2,TDW2);
82
83   Standard_Real param1 = BP1.Parameter();
84   Standard_Real param2 = BP2.Parameter();
85   Standard_Real scal = 1./(param1-param2);
86
87   cout<<endl;
88   cout<<"control derivatives at point : "<<param1<<endl;
89
90   for(i = 1; i <= hp; i++){
91     cout<<endl;
92     cout<<"point : "<<i<<endl;
93     cout<<"dx calculated : "<<TDP1(i).X()<<endl;
94     cout<<"dx estimated  : "<<scal*(TP1(i).X()-TP2(i).X())<<endl;
95     cout<<"dy calculated : "<<TDP1(i).Y()<<endl;
96     cout<<"dy estimated  : "<<scal*(TP1(i).Y()-TP2(i).Y())<<endl;
97     cout<<"dz calculated : "<<TDP1(i).Z()<<endl;
98     cout<<"dz estimated  : "<<scal*(TP1(i).Z()-TP2(i).Z())<<endl;
99     cout<<"dw calculated : "<<TDW1(i)<<endl;
100     cout<<"dw estimated  : "<<scal*(TW1(i)-TW2(i))<<endl;
101   }
102   for(i = 1; i <= hp2d; i++){
103     cout<<endl;
104     cout<<"point 2d : "<<i<<endl;
105     cout<<"dx calculated : "<<TDP2d1(i).X()<<endl;
106     cout<<"dx estimated  : "<<scal*(TP2d1(i).X()-TP2d2(i).X())<<endl;
107     cout<<"dy calculated : "<<TDP2d1(i).Y()<<endl;
108     cout<<"dy estimated  : "<<scal*(TP2d1(i).Y()-TP2d2(i).Y())<<endl;
109   }
110 }
111 #endif
112 static void Drawsect(const Standard_Real param,
113                      Blend_SurfRstFunction& Func)
114 {
115   gp_Pnt pnts = Func.PointOnS();
116   gp_Pnt pntrst = Func.PointOnRst();
117   gp_Pnt2d p2ds = Func.Pnt2dOnS();
118   gp_Pnt2d p2drst = Func.Pnt2dOnRst();
119   Standard_Real w = Func.ParameterOnRst();
120   Blend_Point BP(pnts,pntrst,param,
121                  p2ds.X(),p2ds.Y(),
122                  p2drst.X(),p2drst.Y(),w);
123   Standard_Integer hp,hk,hd,hp2d;
124   Func.GetShape(hp,hk,hd,hp2d);
125   TColStd_Array1OfReal TK(1,hk);
126   Func.Knots(TK);
127   TColStd_Array1OfInteger TMul(1,hk);
128   Func.Mults(TMul);
129   TColgp_Array1OfPnt TP(1,hp);
130   TColgp_Array1OfPnt2d TP2d(1,hp2d);
131   TColStd_Array1OfReal TW(1,hp);
132   Func.Section(BP,TP,TP2d,TW);
133   Handle(Geom_BSplineCurve) sect = new Geom_BSplineCurve
134     (TP,TW,TK,TMul,hd);
135   IndexOfSection++;
136 #ifdef DRAW
137   char tname[100];
138   Standard_CString name = tname ;
139   sprintf(name,"%s_%d","Section",IndexOfSection);
140   DrawTrSurf::Set(name,sect);
141 #endif
142 }
143 #endif
144
145 //=======================================================================
146 //function :  ArcToRecadre
147 //purpose  : Find a suitable arc
148 //           PrevIndex is used to reject an already tested arc
149 //=======================================================================
150
151 Standard_Integer BRepBlend_SurfRstLineBuilder::
152    ArcToRecadre(const math_Vector& theSol,
153                 const Standard_Integer PrevIndex, 
154                 gp_Pnt2d& lastpt2d,
155                 gp_Pnt2d& pt2d,
156                 Standard_Real& ponarc) 
157 {
158   Standard_Integer IndexSol = 0,  nbarc = 0;
159   Standard_Boolean ok = Standard_False;
160   Standard_Boolean byinter = (line->NbPoints() != 0), okinter = 0;
161   Standard_Real distmin = RealLast();
162   Standard_Real uprev = 0.,vprev = 0., prm =  0., dist = 0.;
163
164   if(byinter) previousP.ParametersOnS(uprev,vprev);
165   pt2d.SetCoord(theSol(1),theSol(2));
166   lastpt2d.SetCoord(uprev,vprev);
167   domain1->Init();
168
169   while (domain1->More()) {
170     nbarc++; ok = 0;
171     if(byinter) { 
172       ok = okinter = BRepBlend_BlendTool::Inters(pt2d,lastpt2d,
173                                                  surf1,
174                                                  domain1->Value(),prm,dist); 
175     }
176     if(!ok) ok = BRepBlend_BlendTool::Project(pt2d,surf1,
177                                               domain1->Value(),prm,dist);
178
179     if (ok && (nbarc != PrevIndex) ) {
180       if (dist<distmin || okinter) {
181         distmin = dist;
182         ponarc = prm;
183         IndexSol = nbarc;
184         if(okinter && (PrevIndex==0) ) break;
185       }
186     }
187     domain1->Next();
188   }
189   return IndexSol;
190 }
191
192 //=======================================================================
193 //function : BRepBlend_SurfRstLineBuilder
194 //purpose  : 
195 //=======================================================================
196
197 BRepBlend_SurfRstLineBuilder::BRepBlend_SurfRstLineBuilder
198 (const Handle(Adaptor3d_HSurface)&  Surf1,
199  const Handle(Adaptor3d_TopolTool)& Domain1,
200  const Handle(Adaptor3d_HSurface)&  Surf2,
201  const Handle(Adaptor2d_HCurve2d)&  Rst,
202  const Handle(Adaptor3d_TopolTool)& Domain2):
203  sol(1,3),surf1(Surf1), domain1(Domain1),
204  surf2(Surf2), rst(Rst), domain2(Domain2)
205 {
206 }
207
208 //=======================================================================
209 //function : Perform
210 //purpose  : 
211 //=======================================================================
212
213 void BRepBlend_SurfRstLineBuilder::Perform(Blend_SurfRstFunction&  Func,
214                                            Blend_FuncInv&          Finv,
215                                            Blend_SurfPointFuncInv& FinvP,
216                                            Blend_SurfCurvFuncInv&  FinvC,
217                                            const Standard_Real     Pdep,
218                                            const Standard_Real     Pmax,
219                                            const Standard_Real     MaxStep,
220                                            const Standard_Real     TolGuide,
221                                            const math_Vector&      ParDep,
222                                            const Standard_Real     Tolesp,
223                                            const Standard_Real     Fleche,
224                                            const Standard_Boolean  Appro) 
225 {
226   done = Standard_False;
227   iscomplete = Standard_False;
228   comptra = Standard_False;
229   line = new BRepBlend_Line();
230   tolesp = Abs(Tolesp);
231   tolgui = Abs(TolGuide);
232   fleche = Abs(Fleche);
233   rebrou = Standard_False;
234   pasmax = Abs(MaxStep);
235   
236   if (Pmax-Pdep >= 0.) {
237     sens = 1.;
238   }
239   else {
240     sens = -1.;
241   }
242   
243   Blend_Status State;
244   
245   param = Pdep;
246   Func.Set(param);
247   
248   if (Appro) {
249     TopAbs_State siturst,situs;
250     Standard_Boolean decroch;
251     math_Vector tolerance(1,3),infbound(1,3),supbound(1,3);
252     Func.GetTolerance(tolerance,tolesp);
253     Func.GetBounds(infbound,supbound);
254     math_FunctionSetRoot rsnld(Func,tolerance,30);
255     
256     rsnld.Perform(Func,ParDep,infbound,supbound);
257     
258     if (!rsnld.IsDone()) {
259       return;
260     }
261     rsnld.Root(sol);
262     if (!CheckInside(Func,siturst,situs,decroch)) {
263       return;
264     }
265   }
266   else {
267     sol = ParDep;
268   }
269
270   State = TestArret(Func,Standard_False,Blend_OK);
271   if (State!=Blend_OK) {
272     return;
273   }
274 #ifdef DEB
275   if (Blend_GettraceDRAWSECT()){
276     Drawsect(param,Func);
277   }
278 #endif
279   // Update the line.
280   line->Append(previousP);
281   Standard_Real U,V;
282   previousP.ParametersOnS(U,V);
283 //  W = previousP.ParameterOnC();
284   
285   BRepBlend_Extremity ptf1(previousP.PointOnS(),
286                            U,V,previousP.Parameter(),tolesp);
287   BRepBlend_Extremity ptf2(previousP.PointOnC(),
288                            U,V,previousP.Parameter(),tolesp);
289   if (!previousP.IsTangencyPoint()) {
290     ptf1.SetTangent(previousP.TangentOnS());
291     ptf2.SetTangent(previousP.TangentOnC());
292   }
293   if (sens>0.) {    
294     line->SetStartPoints(ptf1, ptf2);    
295   }
296   else {
297     line->SetEndPoints(ptf1, ptf2);
298     
299   }
300   InternalPerform(Func,Finv,FinvP,FinvC,Pmax);
301   done = Standard_True;
302 }
303
304 //=======================================================================
305 //function : PerformFirstSection
306 //purpose  : 
307 //=======================================================================
308
309 Standard_Boolean BRepBlend_SurfRstLineBuilder::PerformFirstSection
310 (Blend_SurfRstFunction&  Func,
311  Blend_FuncInv&          Finv,
312  Blend_SurfPointFuncInv& FinvP,
313  Blend_SurfCurvFuncInv&  FinvC,
314  const Standard_Real     Pdep,
315  const Standard_Real     Pmax,
316  const math_Vector&      ParDep,
317  const Standard_Real     Tolesp,
318  const Standard_Real     TolGuide,
319  const Standard_Boolean  RecRst,
320  const Standard_Boolean  RecP,
321  const Standard_Boolean  RecS,
322  Standard_Real&          Psol,   
323  math_Vector&            ParSol)
324 {
325   done = Standard_False;
326   iscomplete = Standard_False;
327   comptra = Standard_False;
328   line = new BRepBlend_Line();
329   tolesp = Abs(Tolesp);
330   tolgui = Abs(TolGuide);
331   rebrou = Standard_False;
332   
333   if (Pmax-Pdep >= 0.) {
334     sens = 1.;
335   }
336   else {
337     sens = -1.;
338   }
339   Blend_Status State = Blend_OnRst12;
340   Standard_Real trst = 0.;
341   Standard_Boolean recadp,recadrst,recads;
342   Standard_Real wp,wrst,ws;
343   Standard_Real U = 0.,V = 0.;
344   math_Vector infbound(1,3),supbound(1,3),tolerance(1,3);
345   math_Vector solinvp(1,3),solinvrst(1,4),solinvs(1,3);
346   Handle(Adaptor3d_HVertex) Vtxp,Vtxrst,Vtxs,Vtxc;
347   Standard_Boolean IsVtxp = 0,IsVtxrst = 0,IsVtxs = 0;
348   Handle(Adaptor2d_HCurve2d) Arc;
349   wp = wrst = ws = Pmax;
350   param = Pdep;
351   Func.Set(param);
352   Func.GetTolerance(tolerance,tolesp);
353   Func.GetBounds(infbound,supbound);
354
355   math_FunctionSetRoot rsnld(Func,tolerance,30);
356   rsnld.Perform(Func,ParDep,infbound,supbound);
357   if (!rsnld.IsDone()) return Standard_False;
358   rsnld.Root(sol);
359
360   recads = RecS && Recadre(FinvC,solinvs,Arc,IsVtxs,Vtxs);
361   if (recads) {
362     ws = solinvs(1);
363   }
364   recadp = RecP && Recadre(FinvP,solinvp,IsVtxp,Vtxp);
365   if (recadp) {
366     wp = solinvp(1);
367   }
368   recadrst = RecRst && Recadre(Func,Finv,solinvrst,IsVtxrst,Vtxrst);
369   if (recadrst) {
370     wrst = solinvrst(2);
371   }
372   if (!recads && !recadp && !recadrst) return Standard_False;
373   if (recadp && recadrst) {
374     if(sens*(wrst-wp) > tolgui){ //first one leaves the domain
375       wrst = wp;
376       U = solinvp(2);
377       V = solinvp(3);
378       trst = BRepBlend_BlendTool::Parameter(Vtxp,rst);
379       IsVtxrst = IsVtxp;
380       Vtxrst = Vtxp;
381     }
382     else{                        
383       U = solinvrst(3);
384       V = solinvrst(4);
385       trst = solinvrst(1);
386     }
387   }
388   else if(recadp){
389     wrst = wp;
390     U = solinvp(2);
391     V = solinvp(3);
392     trst = BRepBlend_BlendTool::Parameter(Vtxp,rst);
393     IsVtxrst = IsVtxp;
394     Vtxrst = Vtxp;
395     recadrst = Standard_True;
396   }
397   else if(recadrst){
398     U = solinvrst(3);
399     V = solinvrst(4);
400     trst = solinvrst(1);
401   }
402   if(recads && recadrst){
403     if(Abs(ws - wrst) < tolgui){
404       State = Blend_OnRst12;
405       param = 0.5*(ws+wrst);
406       sol(1) = U;
407       sol(2) = V;
408       sol(3) = solinvs(2);
409     }
410     else if(sens*(ws-wrst)<0){
411       // ground on surf
412       State = Blend_OnRst1;
413       param = ws;
414       Arc->Value(solinvs(3)).Coord(U,V);
415       sol(1) = U;
416       sol(2) = V;
417       sol(3) = solinvs(2);
418     }
419     else{
420       // ground on rst
421       State = Blend_OnRst2;
422       param = wrst;
423       sol(1) = U;
424       sol(2) = V;
425       sol(3) = trst;
426     }
427     Func.Set(param);
428   }
429   else if(recads){
430     // ground on surf
431     State = Blend_OnRst1;
432     param = ws;
433     Arc->Value(solinvs(3)).Coord(U,V);
434     sol(1) = U;
435     sol(2) = V;
436     sol(3) = solinvs(2);
437     Func.Set(param);
438   }
439   else if(recadrst){
440     // ground on rst
441     State = Blend_OnRst2;
442     param = wrst;
443     sol(1) = U;
444     sol(2) = V;
445     sol(3) = trst;
446     Func.Set(param);
447   }
448   State = TestArret(Func,Standard_False,State);
449   Psol = param;
450   ParSol = sol;
451   return Standard_True;
452 }  
453
454 //=======================================================================
455 //function : Complete
456 //purpose  : 
457 //=======================================================================
458
459 Standard_Boolean BRepBlend_SurfRstLineBuilder::Complete(Blend_SurfRstFunction&  Func,
460                                                         Blend_FuncInv&          Finv,
461                                                         Blend_SurfPointFuncInv& FinvP,
462                                                         Blend_SurfCurvFuncInv&  FinvC,
463                                                         const Standard_Real     Pmin) 
464 {
465   if (!done) {StdFail_NotDone::Raise();}
466   if (iscomplete) {return Standard_True;}
467   if (sens >0.) {
468     previousP = line->Point(1);
469   }
470   else {
471     previousP = line->Point(line->NbPoints());
472   }
473   sens = -sens;
474   param = previousP.Parameter();
475   previousP.ParametersOnS(sol(1),sol(2));
476   sol(3) = previousP.ParameterOnC();
477
478   InternalPerform(Func,Finv,FinvP,FinvC,Pmin);
479   iscomplete = Standard_True;
480   return Standard_True;
481 }
482
483 //=======================================================================
484 //function : InternalPerform
485 //purpose  : 
486 //=======================================================================
487
488 void BRepBlend_SurfRstLineBuilder::InternalPerform(Blend_SurfRstFunction&  Func,
489                                                    Blend_FuncInv&          Finv,
490                                                    Blend_SurfPointFuncInv& FinvP,
491                                                    Blend_SurfCurvFuncInv&  FinvC,
492                                                    const Standard_Real     Bound) 
493 {
494   Standard_Real stepw = pasmax;
495   Standard_Integer nbp = line->NbPoints();
496   if(nbp >= 2){ //The last step is reproduced if it is not too small.
497     if(sens < 0.){
498       stepw = (line->Point(2).Parameter() - line->Point(1).Parameter());
499     }
500     else{
501       stepw = (line->Point(nbp).Parameter() - line->Point(nbp - 1).Parameter());
502     }
503     stepw = Max(stepw,100.*tolgui);
504   }
505   Standard_Real parprec = param;
506   if (sens*(parprec - Bound) >= -tolgui) {
507     return;
508   }
509   Blend_Status State = Blend_OnRst12;
510   TopAbs_State situonc = TopAbs_UNKNOWN, situons = TopAbs_UNKNOWN;
511   Standard_Boolean decroch = Standard_False;
512   Standard_Boolean Arrive,recadp,recadrst,recads,echecrecad;
513   Standard_Real wp,wrst,ws;
514   Standard_Real U = 0.,V = 0.;
515   Standard_Real trst = 0.;
516   math_Vector infbound(1,3),supbound(1,3);
517   math_Vector parinit(1,3),tolerance(1,3);
518   math_Vector solinvp(1,3),solinvrst(1,4),solinvs(1,3);
519   Handle(Adaptor3d_HVertex) Vtxp,Vtxrst,Vtxs,Vtxc;
520   Standard_Boolean IsVtxp = 0,IsVtxrst = 0,IsVtxs = 0;
521   BRepBlend_Extremity Extrst,Exts;
522   Handle(Adaptor2d_HCurve2d) Arc;
523
524   //IntSurf_Transition Tline,Tarc;
525
526   Func.GetTolerance(tolerance,tolesp);
527   Func.GetBounds(infbound,supbound);
528
529   math_FunctionSetRoot rsnld(Func,tolerance,30);
530   parinit = sol;
531
532   Arrive = Standard_False;
533   param = parprec + sens*stepw;
534   if(sens *(param - Bound) > 0.) {
535     stepw = sens*(Bound - parprec)*0.5;
536     param = parprec + sens*stepw;
537   }
538
539   while (!Arrive) {
540     Standard_Boolean bonpoint = 1;
541 #ifdef DEB_BBPP_N_TRDERIV
542     //debdebdebdebdebdeb
543     Func.Set(param);
544     rsnld.Perform(Func,parinit,infbound,supbound);
545     if (rsnld.IsDone()) {
546       rsnld.Root(sol);
547       Blend_Point bp1;
548       if(BBPP(param,Func,sol,tolesp,bp1)){
549         Standard_Real dw = 1.e-10;
550         Func.Set(param+dw);
551         rsnld.Perform(Func,parinit,infbound,supbound);
552         if (rsnld.IsDone()) {
553           rsnld.Root(sol);
554           Blend_Point bp2;
555           if(BBPP(param+dw,Func,sol,tolesp,bp2)){
556             tracederiv(Func,bp1,bp2);
557           }
558         }
559       }
560     }
561     //debdebdebdebdebdeb
562 #endif
563     Func.Set(param);
564     rsnld.Perform(Func,parinit,infbound,supbound);
565     
566     if (rsnld.IsDone()) {
567       rsnld.Root(sol);
568       if(!CheckInside(Func,situonc,situons,decroch) && line->NbPoints() == 1){
569         State = Blend_StepTooLarge;
570         bonpoint = 0;
571       }
572     }
573     else {
574       State = Blend_StepTooLarge;
575       bonpoint = 0;
576     }
577     if(bonpoint){
578       wp = wrst = ws = Bound;
579       recadp = recadrst = recads = Standard_False;
580       echecrecad = Standard_False;
581       if (situons == TopAbs_OUT || situons == TopAbs_ON) {
582         // pb inverse rst/rst
583         recads = Recadre(FinvC,solinvs,Arc,IsVtxs,Vtxs);
584         if (recads) {
585           ws = solinvs(1);
586           // It is necessary to reevaluate the deviation (BUC60360)
587           gp_Vec t, n;
588           Func.Set(ws);
589           Arc->Value(solinvs(3)).Coord(U,V);
590           sol(1) = U;
591           sol(2) = V;
592           sol(3) = solinvs(2);
593           decroch = Func.Decroch(sol, t, n); 
594         }
595         else {
596           echecrecad = Standard_True;
597         }
598       }
599       if (situonc == TopAbs_OUT || situonc == TopAbs_ON) {
600         // pb inverse point/surf
601         recadp = Recadre(FinvP,solinvp,IsVtxp,Vtxp);
602         if (recadp) {
603           wp = solinvp(1);
604         }
605         else {
606           echecrecad = Standard_True;
607         }
608       }
609       if (decroch) {
610         // pb inverse rst/surf
611         recadrst = Recadre(Func,Finv,solinvrst,IsVtxrst,Vtxrst);
612         if (recadrst) {
613           wrst = solinvrst(2);
614         }
615         else {
616           echecrecad = Standard_True;
617         }
618       }
619       decroch = 0;
620       if(recadp || recads || recadrst) echecrecad = Standard_False; 
621       if (!echecrecad) {
622         if (recadp && recadrst) {
623           if(sens*(wrst-wp) > tolgui){ //first one leaves the domain
624             wrst = wp;
625             U = solinvp(2);
626             V = solinvp(3);
627             trst = BRepBlend_BlendTool::Parameter(Vtxp,rst);
628             IsVtxrst = IsVtxp;
629             Vtxrst = Vtxp;
630           }
631           else{                        
632             decroch = 1;
633             U = solinvrst(3);
634             V = solinvrst(4);
635             trst = solinvrst(1);
636           }
637         }
638         else if(recadp){
639           wrst = wp;
640           U = solinvp(2);
641           V = solinvp(3);
642           trst = BRepBlend_BlendTool::Parameter(Vtxp,rst);
643           IsVtxrst = IsVtxp;
644           Vtxrst = Vtxp;
645           recadrst = Standard_True;
646         }
647         else if(recadrst){
648           decroch = 1;
649           U = solinvrst(3);
650           V = solinvrst(4);
651           trst = solinvrst(1);
652         }
653         if(recads && recadrst){
654           if(Abs(ws - wrst) < tolgui){
655             State = Blend_OnRst12;
656             param = 0.5*(ws+wrst);
657             sol(1) = U;
658             sol(2) = V;
659             sol(3) = solinvs(3);
660           }
661           else if(sens*(ws-wrst)<0){
662             // ground on surf
663             decroch = 0;
664             State = Blend_OnRst1;
665             param = ws;
666             Arc->Value(solinvs(3)).Coord(U,V);
667             sol(1) = U;
668             sol(2) = V;
669             sol(3) = solinvs(2);
670           }
671           else{
672             // ground on rst
673             State = Blend_OnRst2;
674             param = wrst;
675             sol(1) = U;
676             sol(2) = V;
677             sol(3) = trst;
678           }
679           Func.Set(param);
680         }
681         else if(recads){
682           // ground on surf
683           State = Blend_OnRst1;
684           param = ws;
685           Arc->Value(solinvs(3)).Coord(U,V);
686           sol(1) = U;
687           sol(2) = V;
688           sol(3) = solinvs(2);
689           Func.Set(param);
690         }
691         else if(recadrst){
692           // ground on rst
693           State = Blend_OnRst2;
694           param = wrst;
695           sol(1) = U;
696           sol(2) = V;
697           sol(3) = trst;
698           Func.Set(param);
699         }
700         else {
701           State = Blend_OK;
702         }
703         State = TestArret(Func,Standard_True,State);
704       }
705       else{
706         // Failed reframing. Leave with PointsConfondus
707 #if DEB
708         cout<<"SurfRstLineBuilder : failed reframing"<<endl;
709 #endif
710         State = Blend_SamePoints;
711       }
712     }
713     
714     switch (State) {
715     case Blend_OK :
716       {
717 #ifdef DEB
718         if (Blend_GettraceDRAWSECT()){
719           Drawsect(param,Func);
720         }
721 #endif
722         // Update the line.
723         if (sens>0.) {
724           line->Append(previousP);
725         }
726         else {
727           line->Prepend(previousP);
728         }
729         parinit = sol;
730         parprec = param;
731         
732         if (param == Bound) {
733           Arrive = Standard_True;
734           Exts.SetValue(previousP.PointOnS(),
735                         sol(1),sol(2),
736                         previousP.Parameter(),tolesp);
737           MakeExtremity(Extrst,Standard_False,rst,sol(3),IsVtxrst,Vtxrst);
738           // Indicate end on Bound.
739         }
740         else {
741           param = param + sens*stepw;
742           if (sens*(param - Bound) > - tolgui) {
743             param = Bound;
744           }
745         }
746       }
747       break;
748       
749     case Blend_StepTooLarge :
750       {
751         stepw = stepw/2.;
752         if (Abs(stepw) < tolgui) {
753           previousP.ParametersOnS(U,V);
754           Exts.SetValue(previousP.PointOnS(),U,V,
755                         previousP.Parameter(),tolesp);
756           Extrst.SetValue(previousP.PointOnC(),
757                           previousP.ParameterOnC(),
758                           previousP.Parameter(),tolesp);
759           Arrive = Standard_True;
760           if (line->NbPoints()>=2) {
761             // Indicate that one stops during the processing
762 #if DEB
763             cout<<"SurfRstLineBuilder : No advancement in the processing"<<endl;
764 #endif
765           }
766         }
767         else {
768           param = parprec + sens*stepw;  // no risk to exceed Bound.
769         }
770       }
771       break;
772       
773     case Blend_StepTooSmall :
774       {
775 #ifdef DEB
776         if (Blend_GettraceDRAWSECT()){
777           Drawsect(param,Func);
778         }
779 #endif
780         // Update the line.
781         if (sens>0.) {
782           line->Append(previousP);
783         }
784         else {
785           line->Prepend(previousP);
786         }
787         parinit = sol;
788         parprec = param;
789         
790         stepw = Min(1.5*stepw,pasmax);
791         if (param == Bound) {
792           Arrive = Standard_True;
793           Exts.SetValue(previousP.PointOnS(),sol(1),sol(2),
794                         previousP.Parameter(),tolesp);
795           MakeExtremity(Extrst,Standard_False,rst,sol(3),IsVtxrst,Vtxrst);
796           // Indicate end on Bound.
797         }
798         else {
799           param = param + sens*stepw;
800           if (sens*(param - Bound) > - tolgui) {
801             param = Bound;
802           }
803         }
804       }
805       break;
806       
807     case Blend_OnRst1  :
808       {
809 #ifdef DEB
810         if (Blend_GettraceDRAWSECT()){
811           Drawsect(param,Func);
812         }
813 #endif
814         if (sens>0.) {
815           line->Append(previousP);
816         }
817         else {
818           line->Prepend(previousP);
819         }
820         MakeExtremity(Exts,Standard_True,Arc,solinvs(3),IsVtxs,Vtxs);
821         MakeExtremity(Extrst,Standard_False,rst,sol(3),IsVtxrst,Vtxrst);
822         Arrive = Standard_True;
823       }
824       break;
825       
826     case Blend_OnRst2  :
827       {
828 #ifdef DEB
829         if (Blend_GettraceDRAWSECT()){
830           Drawsect(param,Func);
831         }
832 #endif
833         if (sens>0.) {
834           line->Append(previousP);
835         }
836         else {
837           line->Prepend(previousP);
838         }
839         Exts.SetValue(previousP.PointOnS(),sol(1),sol(2),
840                       previousP.Parameter(),tolesp);
841         MakeExtremity(Extrst,Standard_False,rst,sol(3),IsVtxrst,Vtxrst);
842         Arrive = Standard_True;
843       }
844       break;
845       
846     case Blend_OnRst12  :
847       {
848 #ifdef DEB
849         if (Blend_GettraceDRAWSECT()){
850           Drawsect(param,Func);
851         }
852 #endif
853         if (sens>0.) {
854           line->Append(previousP);
855         }
856         else {
857           line->Prepend(previousP);
858         }
859         MakeExtremity(Exts,Standard_True,Arc,solinvs(1),IsVtxs,Vtxs);
860         MakeExtremity(Extrst,Standard_False,rst,sol(3),IsVtxrst,Vtxrst);
861         Arrive = Standard_True;
862       }
863       break;
864       
865     case Blend_SamePoints :
866       {
867         // Stop
868 #if DEB
869         cout << "SurfRstLineBuilder Points mixed in the processing" << endl;
870 #endif
871         previousP.ParametersOnS(U,V);
872         Exts.SetValue(previousP.PointOnS(),U,V,
873                       previousP.Parameter(),tolesp);
874         Extrst.SetValue(previousP.PointOnC(),
875                         previousP.ParameterOnC(),
876                         previousP.Parameter(),tolesp);
877         Arrive = Standard_True;
878       }
879       break;
880     default:
881       break;
882     }
883     if (Arrive) {
884       if (sens > 0.) {
885         line->SetEndPoints(Exts,Extrst);
886         decrochfin = decroch;
887       }
888       else {
889         line->SetStartPoints(Exts,Extrst);
890         decrochdeb = decroch;
891       }
892     }
893   }
894 }
895
896 //=======================================================================
897 //function : Recadre
898 //purpose  : Reframe section Surface / Restriction
899 //=======================================================================
900
901 Standard_Boolean BRepBlend_SurfRstLineBuilder::Recadre(Blend_SurfCurvFuncInv&    FinvC,
902                                                        math_Vector&              Solinv,
903                                                        Handle(Adaptor2d_HCurve2d)& Arc,
904                                                        Standard_Boolean&         IsVtx,
905                                                        Handle(Adaptor3d_HVertex)&  Vtx) 
906 {
907   Standard_Boolean recadre = Standard_False;
908
909   gp_Pnt2d pt2d, lastpt2d;
910   Standard_Integer IndexSol, nbarc;
911   Standard_Real pmin;
912
913   IndexSol = ArcToRecadre(sol, 0, lastpt2d, pt2d, pmin);
914  
915   IsVtx = Standard_False;
916   if (IndexSol == 0) {
917     return Standard_False;
918   }
919
920   domain1->Init();
921   nbarc = 1;
922   while (nbarc < IndexSol) {
923     nbarc++;
924     domain1->Next();
925   }
926   Arc = domain1->Value();
927
928   FinvC.Set(Arc);
929   
930   math_Vector toler(1,3),infb(1,3),supb(1,3);
931   FinvC.GetTolerance(toler,tolesp);
932   FinvC.GetBounds(infb,supb);
933   Solinv(1) = param;
934   Solinv(2) = sol(3);
935   Solinv(3) = pmin;
936   
937   math_FunctionSetRoot rsnld(FinvC,toler,30);
938   rsnld.Perform(FinvC,Solinv,infb,supb);
939
940   if (!rsnld.IsDone()) {
941 #if DEB
942     cout << "SurfRstLineBuilder : RSNLD not done "<< endl << endl;
943 #endif
944   }
945   else {
946       // It is necessary to check the value of the function
947     rsnld.Root(Solinv);
948     recadre = FinvC.IsSolution(Solinv,tolesp);
949   }
950
951   // In case of fail, it is checked if another arc 
952   // can be useful (case of output at the proximity of a vertex)
953   if (!recadre) {
954
955     IndexSol =  ArcToRecadre(sol, IndexSol, 
956                              lastpt2d, pt2d, pmin);
957     if (IndexSol == 0) {
958       return Standard_False; // No other solution
959     }
960
961     domain1->Init();
962     nbarc = 1;
963     while (nbarc < IndexSol) {
964       nbarc++;
965       domain1->Next();
966     }
967
968     Arc = domain1->Value();
969     FinvC.Set(Arc);
970   
971     FinvC.GetTolerance(toler,tolesp);
972     FinvC.GetBounds(infb,supb);
973
974     Solinv(3) = pmin;
975   
976     math_FunctionSetRoot rsnld(FinvC,toler,30);
977     rsnld.Perform(FinvC,Solinv,infb,supb);
978
979     if (!rsnld.IsDone()) {
980 #if DEB
981       cout << "SurfRstLineBuilder : RSNLD not done "<< endl << endl;
982 #endif
983     }
984     else {
985       // It is necessary to check the value of the function
986       rsnld.Root(Solinv);
987       recadre = FinvC.IsSolution(Solinv,tolesp);
988     }
989   }  
990
991   if (recadre) {
992     Standard_Real w = Solinv(2);
993     if(w < rst->FirstParameter() - toler(2)||
994        w > rst->LastParameter() + toler(2)){
995       return Standard_False;
996     }
997     domain1->Initialize(Arc);
998     domain1->InitVertexIterator();
999     IsVtx = !domain1->MoreVertex();
1000     while (!IsVtx) {
1001       Vtx = domain1->Vertex();
1002       if (Abs(BRepBlend_BlendTool::Parameter(Vtx,Arc)-Solinv(3)) <=
1003           BRepBlend_BlendTool::Tolerance(Vtx,Arc)) {
1004         IsVtx = Standard_True;
1005       }
1006       else {
1007         domain1->NextVertex();
1008         IsVtx = !domain1->MoreVertex();
1009       }
1010     }
1011     if (!domain1->MoreVertex()) {
1012       IsVtx = Standard_False;
1013     }
1014     return Standard_True;
1015   } 
1016   return Standard_False;
1017 }
1018
1019 //=======================================================================
1020 //function : Recadre
1021 //purpose  : 
1022 //=======================================================================
1023
1024 Standard_Boolean BRepBlend_SurfRstLineBuilder::Recadre(Blend_SurfRstFunction&   Func,
1025                                                        Blend_FuncInv&           Finv,
1026                                                        math_Vector&             Solinv,
1027                                                        Standard_Boolean&        IsVtx,
1028                                                        Handle(Adaptor3d_HVertex)& Vtx) 
1029 {
1030   math_Vector toler(1,4),infb(1,4),supb(1,4);
1031   Finv.GetTolerance(toler,tolesp);
1032   Finv.GetBounds(infb,supb);
1033   Solinv(1) = sol(3);
1034   Solinv(2) = param;
1035   Solinv(3) = sol(1);
1036   Solinv(4) = sol(2);
1037
1038   math_FunctionSetRoot rsnld(Finv,toler,30);
1039   rsnld.Perform(Finv,Solinv,infb,supb);
1040   if (!rsnld.IsDone()) {
1041 #if DEB
1042     cout << "SurfRstLineBuilder :RSNLD not done "<< endl;
1043 #endif
1044     return Standard_False;
1045   }
1046   rsnld.Root(Solinv);
1047   
1048   if(Finv.IsSolution(Solinv,tolesp)){
1049     gp_Pnt2d p2d(Solinv(3),Solinv(4));
1050     TopAbs_State situ = domain1->Classify(p2d,Min(toler(3),toler(4)),0);
1051     if ((situ != TopAbs_IN) && (situ != TopAbs_ON)) {
1052       return Standard_False;
1053     }
1054     domain2->Initialize(rst);
1055     domain2->InitVertexIterator();
1056     IsVtx = !domain2->MoreVertex();
1057     while (!IsVtx) {
1058       Vtx = domain2->Vertex();
1059       if (Abs(BRepBlend_BlendTool::Parameter(Vtx,rst)-Solinv(1)) <=
1060           BRepBlend_BlendTool::Tolerance(Vtx,rst)) {
1061         IsVtx = Standard_True;
1062       }
1063       else {
1064         domain2->NextVertex();
1065         IsVtx = !domain2->MoreVertex();
1066       }
1067     }
1068     if (!domain2->MoreVertex()) {
1069       IsVtx = Standard_False;
1070     }
1071     // The section is recalculated by direct resolution, otherwise 
1072     // incoherences between the parameter and the ground caused by yawn are returned.
1073
1074     math_Vector infbound(1,3),supbound(1,3);
1075     math_Vector parinit(1,3),tolerance(1,3);
1076     Func.GetTolerance(tolerance,tolesp);
1077     Func.GetBounds(infbound,supbound);
1078
1079     math_FunctionSetRoot rsnld2(Func,tolerance,30);
1080     parinit(1) = Solinv(3);
1081     parinit(2) = Solinv(4);
1082     parinit(3) = Solinv(1);
1083     Func.Set(Solinv(2));
1084     rsnld2.Perform(Func,parinit,infbound,supbound);
1085     if(!rsnld2.IsDone()) return Standard_False;
1086     rsnld2.Root(parinit);
1087     Solinv(3) = parinit(1);
1088     Solinv(4) = parinit(2);
1089     Solinv(1) = parinit(3);
1090     return Standard_True;
1091   }
1092   return Standard_False;
1093 }
1094
1095 //=======================================================================
1096 //function : Recadre
1097 //purpose  : 
1098 //=======================================================================
1099
1100 Standard_Boolean BRepBlend_SurfRstLineBuilder::Recadre(Blend_SurfPointFuncInv&  FinvP,
1101                                                        math_Vector&             Solinv,
1102                                                        Standard_Boolean&        IsVtx,
1103                                                        Handle(Adaptor3d_HVertex)& Vtx) 
1104 {
1105   // Le point.
1106   gp_Pnt2d p2drst;
1107   Standard_Real firstrst = rst->FirstParameter();
1108   Standard_Real lastrst = rst->LastParameter();
1109   Standard_Real wpoint = firstrst;
1110   if((sol(3) - firstrst) > (lastrst - sol(3))) wpoint = lastrst;
1111   p2drst = rst->Value(wpoint);
1112   gp_Pnt thepoint = surf2->Value(p2drst.X(),p2drst.Y());
1113
1114   FinvP.Set(thepoint);
1115   math_Vector toler(1,3),infb(1,3),supb(1,3);
1116   FinvP.GetTolerance(toler,tolesp);
1117   FinvP.GetBounds(infb,supb);
1118   Solinv(1) = param;
1119   Solinv(2) = sol(1);
1120   Solinv(3) = sol(2);
1121
1122   math_FunctionSetRoot rsnld(FinvP,toler,30);
1123   rsnld.Perform(FinvP,Solinv,infb,supb);
1124   if (!rsnld.IsDone()) {
1125 #if DEB
1126     cout << "SurfRstLineBuilder :RSNLD not done "<< endl;
1127 #endif
1128     return Standard_False;
1129   }
1130   rsnld.Root(Solinv);
1131   
1132   if(FinvP.IsSolution(Solinv,tolesp)){
1133     gp_Pnt2d p2d(Solinv(2),Solinv(3));
1134     TopAbs_State situ = domain1->Classify(p2d,Min(toler(2),toler(3)),0);
1135     if ((situ != TopAbs_IN) && (situ != TopAbs_ON)) {
1136       return Standard_False;
1137     }
1138     domain2->Initialize(rst);
1139     domain2->InitVertexIterator();
1140     IsVtx = !domain2->MoreVertex();
1141     while (!IsVtx) {
1142       Vtx = domain2->Vertex();
1143       if (Abs(BRepBlend_BlendTool::Parameter(Vtx,rst)-wpoint) <=
1144           BRepBlend_BlendTool::Tolerance(Vtx,rst)) {
1145         IsVtx = Standard_True;
1146       }
1147       else {
1148         domain2->NextVertex();
1149         IsVtx = !domain2->MoreVertex();
1150       }
1151     }
1152     if (!domain2->MoreVertex()) {
1153       IsVtx = Standard_False;
1154     }
1155     return Standard_True;
1156   }
1157   return Standard_False;
1158 }
1159
1160 //=======================================================================
1161 //function : Transition
1162 //purpose  : 
1163 //=======================================================================
1164
1165 void BRepBlend_SurfRstLineBuilder::Transition(const Standard_Boolean          OnFirst,
1166                                               const Handle(Adaptor2d_HCurve2d)& Arc,
1167                                               const Standard_Real             Param,
1168                                               IntSurf_Transition&             TLine,
1169                                               IntSurf_Transition&             TArc) 
1170 {
1171   Standard_Boolean computetranstionaveclacorde = 0;
1172   gp_Vec tgline;
1173   Blend_Point prevprev;
1174
1175   if(previousP.IsTangencyPoint()){
1176     if(line->NbPoints() < 2) return;
1177     computetranstionaveclacorde = 1;
1178     if(sens < 0){
1179       prevprev = line->Point(2);
1180     }
1181     else {
1182       prevprev = line->Point(line->NbPoints() - 1);
1183     }
1184   }
1185   gp_Pnt2d p2d;
1186   gp_Vec2d dp2d;
1187   
1188   gp_Pnt pbid;
1189   gp_Vec d1u,d1v,normale,tgrst;
1190   
1191   Arc->D1(Param,p2d,dp2d);
1192   if (OnFirst) {
1193     surf1->D1(p2d.X(),p2d.Y(),pbid,d1u,d1v);
1194     if(!computetranstionaveclacorde) tgline = previousP.TangentOnS1();
1195     else tgline = gp_Vec(prevprev.PointOnS(),previousP.PointOnS());
1196   }
1197   else {
1198     surf2->D1(p2d.X(),p2d.Y(),pbid,d1u,d1v);
1199     if(!computetranstionaveclacorde) tgline = previousP.TangentOnS2();
1200     else tgline = gp_Vec(prevprev.PointOnC(),previousP.PointOnC());
1201   }
1202   
1203   tgrst.SetLinearForm(dp2d.X(),d1u,dp2d.Y(),d1v);
1204   normale = d1u.Crossed(d1v);
1205   
1206   IntSurf::MakeTransition(tgline,tgrst,normale,TLine,TArc);
1207 }
1208
1209 //=======================================================================
1210 //function : MakeExtremity
1211 //purpose  : 
1212 //=======================================================================
1213
1214 void BRepBlend_SurfRstLineBuilder::MakeExtremity(BRepBlend_Extremity&            Extrem,
1215                                                  const Standard_Boolean          OnFirst,
1216                                                  const Handle(Adaptor2d_HCurve2d)& Arc,
1217                                                  const Standard_Real             Param,
1218                                                  const Standard_Boolean          IsVtx,
1219                                                  const Handle(Adaptor3d_HVertex)&  Vtx) 
1220 {
1221   IntSurf_Transition Tline,Tarc;
1222   Standard_Real prm;
1223   Handle(Adaptor3d_TopolTool) Iter;
1224   if (OnFirst) {
1225     Extrem.SetValue(previousP.PointOnS(),
1226                     sol(1),sol(2),
1227                     previousP.Parameter(),tolesp);
1228     if (!previousP.IsTangencyPoint()) 
1229       Extrem.SetTangent(previousP.TangentOnS());
1230     Iter = domain1;
1231   }
1232   else {
1233     Extrem.SetValue(previousP.PointOnC(),
1234                     sol(3),
1235                     previousP.Parameter(),tolesp);
1236     if (!previousP.IsTangencyPoint()) 
1237       Extrem.SetTangent(previousP.TangentOnC());    
1238     Iter = domain2;
1239   }
1240   
1241   Iter->Init();
1242   if (!IsVtx) {
1243     Transition(OnFirst,Arc,Param,Tline,Tarc);
1244     Extrem.AddArc(Arc,Param,Tline,Tarc);
1245   }
1246   else {
1247     Extrem.SetVertex(Vtx);
1248     while (Iter->More()) {
1249       Handle(Adaptor2d_HCurve2d) arc = Iter->Value();
1250       if (arc != Arc) {
1251         Iter->Initialize(arc);
1252         Iter->InitVertexIterator();
1253         while (Iter->MoreVertex()) {
1254           if (Iter->Identical(Vtx,Iter->Vertex())) {
1255             prm = BRepBlend_BlendTool::Parameter(Vtx,arc);
1256             Transition(OnFirst,arc,prm,Tline,Tarc);
1257             Extrem.AddArc(arc,prm,Tline,Tarc);
1258           }
1259           Iter->NextVertex();
1260         }
1261       }
1262       else {
1263         Transition(OnFirst,arc,Param,Tline,Tarc);
1264         Extrem.AddArc(arc,Param,Tline,Tarc);
1265       }
1266       Iter->Next();
1267     }
1268   }
1269 }
1270
1271 //=======================================================================
1272 //function : CheckDeflectionOnSurf
1273 //purpose  : 
1274 //=======================================================================
1275
1276 Blend_Status BRepBlend_SurfRstLineBuilder::CheckDeflectionOnSurf(const Blend_Point& CurPoint)
1277 {
1278   //Controls 3d of Blend_CSWalking.
1279
1280   //rule by tests in U4 corresponds to 11.478 d
1281   const Standard_Real CosRef3D = 0.98;
1282   Standard_Real Cosi=0, Cosi2=0;
1283   Standard_Boolean curpointistangent = CurPoint.IsTangencyPoint();
1284   Standard_Boolean prevpointistangent = previousP.IsTangencyPoint();
1285
1286   gp_Pnt Psurf = CurPoint.PointOnS();
1287   gp_Vec Tgsurf;
1288   if(!curpointistangent){
1289     Tgsurf = CurPoint.TangentOnS();
1290   }
1291   gp_Pnt prevP = previousP.PointOnS();
1292   gp_Vec prevTg;
1293   if(!prevpointistangent){
1294     prevTg = previousP.TangentOnS();
1295   }
1296   Standard_Real Norme,prevNorme = 0.;
1297   gp_Vec Corde(prevP,Psurf);
1298   Norme = Corde.SquareMagnitude();
1299 //  if(!curpointistangent) curNorme = Tgsurf.SquareMagnitude();
1300   if(!prevpointistangent) prevNorme = prevTg.SquareMagnitude();
1301
1302   if (Norme <= tolesp*tolesp){
1303     // it can be necessary to force same point
1304     return Blend_SamePoints;
1305   }
1306   if(!prevpointistangent){
1307     if(prevNorme <= tolesp*tolesp) {
1308       return Blend_SamePoints;
1309     }
1310     Cosi = sens*Corde*prevTg;
1311     if (Cosi <0.) { // angle 3d>pi/2. --> return back
1312       return Blend_Backward;
1313     }
1314     
1315     Cosi2 = Cosi * Cosi / prevNorme / Norme;
1316     if (Cosi2 < CosRef3D) { 
1317       return Blend_StepTooLarge;
1318     }
1319   }
1320   
1321   if(!curpointistangent){
1322     // Check if it is necessary to control the sign of prevtg*Tgsurf
1323     Cosi = sens*Corde*Tgsurf;
1324     Cosi2 = Cosi * Cosi / Tgsurf.SquareMagnitude() / Norme;
1325     if (Cosi2 < CosRef3D || Cosi < 0.) { 
1326       return Blend_StepTooLarge;
1327     }
1328   }  
1329
1330   if(!curpointistangent && !prevpointistangent){
1331     // Estimation of the current arrow
1332     Standard_Real FlecheCourante = 
1333       (prevTg.Normalized().XYZ()-Tgsurf.Normalized().XYZ()).SquareModulus()*Norme/64.;
1334     
1335     if (FlecheCourante <= 0.25*fleche*fleche) {
1336       return Blend_StepTooSmall;
1337     }
1338     if (FlecheCourante > fleche*fleche) {
1339       // not too great : 
1340       return Blend_StepTooLarge;
1341     }
1342   }
1343   return Blend_OK;
1344 }
1345
1346
1347 //=======================================================================
1348 //function : CheckDeflectionOnRst
1349 //purpose  : 
1350 //=======================================================================
1351
1352 Blend_Status BRepBlend_SurfRstLineBuilder::CheckDeflectionOnRst(const Blend_Point& CurPoint)
1353 {
1354   //Controls 3D of Blend_CSWalking.
1355
1356   // rule by tests in U4 corresponds to 11.478 d
1357   const Standard_Real CosRef3D = 0.98;
1358   Standard_Real Cosi, Cosi2;
1359   Standard_Boolean curpointistangent = CurPoint.IsTangencyPoint();
1360   Standard_Boolean prevpointistangent = previousP.IsTangencyPoint();
1361
1362   gp_Pnt Psurf = CurPoint.PointOnC();
1363   gp_Vec Tgsurf;
1364   if(!curpointistangent){
1365     Tgsurf = CurPoint.TangentOnC();
1366   }
1367   gp_Pnt prevP = previousP.PointOnC();
1368   gp_Vec prevTg;
1369   if(!prevpointistangent){
1370     prevTg = previousP.TangentOnC();
1371   }
1372   Standard_Real Norme,prevNorme = 0.;
1373   gp_Vec Corde(prevP,Psurf);
1374   Norme = Corde.SquareMagnitude();
1375 //  if(!curpointistangent) curNorme = Tgsurf.SquareMagnitude();
1376   if(!prevpointistangent) prevNorme = prevTg.SquareMagnitude();
1377
1378   if (Norme <= tolesp*tolesp){
1379     // it can be necessary to force same point
1380     return Blend_SamePoints;
1381   }
1382   if(!prevpointistangent){
1383     if(prevNorme <= tolesp*tolesp) {
1384       return Blend_SamePoints;
1385     }
1386     Cosi = sens*Corde*prevTg;
1387     if (Cosi <0.) { // angle 3d>pi/2. --> return back
1388       return Blend_Backward;
1389     }
1390     
1391     Cosi2 = Cosi * Cosi / prevNorme / Norme;
1392     if (Cosi2 < CosRef3D) { 
1393       return Blend_StepTooLarge;
1394     }
1395   }
1396   
1397   if(!curpointistangent){
1398     // Check if it is necessary to control the sign of prevtg*Tgsurf
1399     Cosi = sens*Corde*Tgsurf;
1400     Cosi2 = Cosi * Cosi / Tgsurf.SquareMagnitude() / Norme;
1401     if (Cosi2 < CosRef3D || Cosi < 0.) { 
1402       return Blend_StepTooLarge;
1403     }
1404   }  
1405
1406   if(!curpointistangent && !prevpointistangent){
1407     // Estimation of the current arrow
1408     Standard_Real FlecheCourante = 
1409       (prevTg.Normalized().XYZ()-Tgsurf.Normalized().XYZ()).SquareModulus()*Norme/64.;
1410     
1411     if (FlecheCourante <= 0.25*fleche*fleche) {
1412       return Blend_StepTooSmall;
1413     }
1414     if (FlecheCourante > fleche*fleche) {
1415       // not too great
1416       return Blend_StepTooLarge;
1417     }
1418   }
1419   return Blend_OK;
1420 }
1421
1422 static IntSurf_TypeTrans ConvOrToTra(const TopAbs_Orientation O)
1423 {
1424   if(O == TopAbs_FORWARD) return IntSurf_In;
1425   return IntSurf_Out;
1426 }
1427
1428 //=======================================================================
1429 //function : TestArret
1430 //purpose  : 
1431 //=======================================================================
1432
1433 Blend_Status BRepBlend_SurfRstLineBuilder::TestArret(Blend_SurfRstFunction& Func,
1434                                                      const Standard_Boolean TestDeflection,
1435                                                      const Blend_Status     State) 
1436 {
1437   gp_Pnt pts,ptrst;
1438   gp_Pnt2d pt2drst;
1439   gp_Vec tgs,tgrst;
1440   gp_Vec2d tg2ds,tg2drst;
1441   Blend_Status StateS,StateRst;
1442   IntSurf_TypeTrans tras = IntSurf_Undecided, trarst = IntSurf_Undecided;
1443   Blend_Point curpoint;
1444
1445   if (Func.IsSolution(sol,tolesp)) {
1446     Standard_Boolean curpointistangent = Func.IsTangencyPoint();
1447     pts = Func.PointOnS();
1448     ptrst = Func.PointOnRst();
1449     pt2drst = Func.Pnt2dOnRst();
1450     if(curpointistangent){
1451       curpoint.SetValue(pts,ptrst,param,sol(1),sol(2),
1452                         pt2drst.X(),pt2drst.Y(),sol(3));
1453     }
1454     else{
1455       tgs     = Func.TangentOnS();
1456       tgrst   = Func.TangentOnRst();
1457       tg2ds   = Func.Tangent2dOnS();
1458       tg2drst = Func.Tangent2dOnRst();
1459
1460       curpoint.SetValue(pts,ptrst,param,sol(1),sol(2),
1461                         pt2drst.X(),pt2drst.Y(),sol(3),
1462                         tgs,tgrst,tg2ds,tg2drst);
1463     }
1464     if (TestDeflection) {
1465       StateS = CheckDeflectionOnSurf(curpoint);
1466       StateRst = CheckDeflectionOnRst(curpoint);
1467     }
1468     else {
1469       StateS = StateRst = Blend_OK;
1470     }
1471     if (StateS == Blend_Backward) {
1472       StateS = Blend_StepTooLarge;
1473       rebrou= Standard_True;
1474     }
1475     if (StateRst == Blend_Backward) {
1476       StateRst = Blend_StepTooLarge;
1477       rebrou = Standard_True;
1478     }
1479     if (StateS == Blend_StepTooLarge ||
1480         StateRst == Blend_StepTooLarge) {
1481       return Blend_StepTooLarge;
1482     }
1483
1484     if (!comptra && !curpointistangent) {
1485       gp_Vec tgsecs,nors;
1486       Func.Decroch(sol,nors,tgsecs);
1487       nors.Normalize();
1488       Standard_Real testra = tgsecs.Dot(nors.Crossed(tgs));
1489       if (Abs(testra) > tolesp) {
1490         if (testra < 0.) {
1491           tras = IntSurf_In;
1492         }
1493         else if (testra >0.) {
1494           tras = IntSurf_Out;
1495         }
1496         gp_Pnt2d p2drstref; gp_Vec2d tg2drstref;
1497         rst->D1(sol(3),p2drstref,tg2drstref);
1498         testra = tg2drst.Dot(tg2drstref);
1499         TopAbs_Orientation Or = domain2->Orientation(rst);
1500         if (Abs(testra) > 1.e-8) {
1501           if (testra < 0.) {
1502             trarst = ConvOrToTra(TopAbs::Reverse(Or));
1503           }
1504           else if (testra >0.) {
1505             trarst = ConvOrToTra(Or);
1506           }
1507           comptra = Standard_True;
1508           line->Set(tras,trarst);
1509         }
1510       }
1511     }
1512     if (StateS == Blend_OK ||
1513         StateRst == Blend_OK ) {
1514       previousP = curpoint;
1515       return State;
1516     }
1517     if (StateS == Blend_StepTooSmall &&
1518         StateRst == Blend_StepTooSmall) {
1519       previousP = curpoint;
1520       if (State == Blend_OK) {
1521         return Blend_StepTooSmall;
1522       }
1523       else {
1524         return State;
1525       }
1526     }
1527     if (State == Blend_OK) {
1528       return Blend_SamePoints;
1529     }
1530     else {
1531       return State;
1532     }
1533   }
1534   return Blend_StepTooLarge;
1535 }
1536
1537 //=======================================================================
1538 //function : CheckInside
1539 //purpose  : 
1540 //=======================================================================
1541
1542 Standard_Boolean BRepBlend_SurfRstLineBuilder::CheckInside(Blend_SurfRstFunction& Func,
1543                                                            TopAbs_State&          SituOnC,
1544                                                            TopAbs_State&          SituOnS,
1545                                                            Standard_Boolean&      Decroch)
1546 {
1547   math_Vector tolerance(1,3);
1548   Func.GetTolerance(tolerance,tolesp);
1549   //face pcurve.
1550   Standard_Real w = sol(3);
1551   if(w < rst->FirstParameter() - tolerance(3)||
1552      w > rst->LastParameter() + tolerance(3)){
1553     SituOnC = TopAbs_OUT;
1554   }
1555   else if (w > rst->FirstParameter() &&
1556            w < rst->LastParameter()){
1557     SituOnC = TopAbs_IN;
1558   }
1559   else SituOnC = TopAbs_ON;
1560
1561   //face surface
1562   gp_Pnt2d p2d(sol(1),sol(2));
1563   SituOnS = domain1->Classify(p2d,Min(tolerance(1),tolerance(2)),0);
1564
1565   //lost contact
1566   gp_Vec tgs,nors;
1567   Decroch = Func.Decroch(sol,tgs,nors);
1568
1569   return (SituOnC == TopAbs_IN && SituOnS == TopAbs_IN && !Decroch);
1570 }
1571