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