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