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