0024059: Eliminate compiler warning C4701 in MSVC++ with warning level 4
[occt.git] / src / Blend / Blend_Walking_4.gxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19 static void evalpinit(math_Vector& parinit,
20                       const Blend_Point& previousP,
21                       const Standard_Real parprec,
22                       const Standard_Real param,
23                       const math_Vector& infbound,
24                       const math_Vector& supbound,
25                       const Standard_Boolean classonS1, 
26                       const Standard_Boolean classonS2)
27 {
28   if(previousP.IsTangencyPoint()){
29     previousP.ParametersOnS1(parinit(1),parinit(2));
30     previousP.ParametersOnS2(parinit(3),parinit(4));
31   }
32   else {
33     Standard_Real u1,v1,u2,v2;
34     Standard_Real du1,dv1,du2,dv2;
35     Standard_Boolean Inside=Standard_True;
36     previousP.ParametersOnS1(u1,v1);
37     previousP.ParametersOnS2(u2,v2);
38     previousP.Tangent2dOnS1().Coord(du1,dv1);
39     previousP.Tangent2dOnS2().Coord(du2,dv2);
40     Standard_Real step = param - parprec;
41     u1+= step*du1;
42     v1+= step*dv1;
43     if ( classonS1 ) {
44       if ((u1<infbound(1)) || (u1>supbound(1))) Inside=Standard_False;
45       if ((v1<infbound(2)) || (v1>supbound(2))) Inside=Standard_False;
46     }
47     u2+= step*du2;
48     v2+= step*dv2;
49     if ( classonS2) {
50       if ((u2<infbound(3)) || (u2>supbound(3))) Inside=Standard_False;
51       if ((v2<infbound(4)) || (v2>supbound(4))) Inside=Standard_False;
52     }
53
54     if (Inside) {
55       parinit(1) = u1;
56       parinit(2) = v1;
57       parinit(3) = u2;
58       parinit(4) = v2;
59     }
60     else { // on ne joue pas au plus malin
61       previousP.ParametersOnS1(parinit(1),parinit(2));
62       previousP.ParametersOnS2(parinit(3),parinit(4));
63     }
64     
65   }
66 }
67
68
69
70 void Blend_Walking::InternalPerform(Blend_Function& Func,
71                                     Blend_FuncInv& FuncInv,
72                                     const Standard_Real Bound)
73 {
74
75   Standard_Real stepw = pasmax;
76   Standard_Integer nbp = line->NbPoints();
77   if(nbp >= 2){ //On reprend le dernier step s'il n est pas trop petit.
78     if(sens < 0.){
79       stepw = (line->Point(2).Parameter() - line->Point(1).Parameter());
80     }
81     else{
82       stepw = (line->Point(nbp).Parameter() - line->Point(nbp - 1).Parameter());
83     }
84     stepw = Max(stepw,100.*tolgui);
85   }
86   Standard_Real parprec = param;
87
88   if (sens*(parprec - Bound) >= -tolgui) {
89     return;
90   }
91   Blend_Status State = Blend_OnRst12;
92   TopAbs_State situ1 =TopAbs_IN,situ2=TopAbs_IN;
93   Standard_Real w1,w2;
94   Standard_Integer Index1 = 0, Index2 = 0, nbarc;
95   Standard_Boolean Arrive,recad1,recad2, control;
96   Standard_Boolean Isvtx1 = Standard_False, Isvtx2 = Standard_False, echecrecad;
97   gp_Pnt2d p2d;
98   math_Vector tolerance(1,4),infbound(1,4),supbound(1,4),parinit(1,4);
99   math_Vector solrst1(1,4),solrst2(1,4);
100   TheVertex Vtx1,Vtx2;
101   TheExtremity Ext1,Ext2;
102
103   //IntSurf_Transition Tline,Tarc;
104
105   Func.GetTolerance(tolerance,tolesp);
106   Func.GetBounds(infbound,supbound);
107
108   math_FunctionSetRoot rsnld(Func,tolerance,30);
109   parinit = sol;
110
111   Arrive = Standard_False;
112   param = parprec + sens*stepw;
113   if(sens *(param - Bound) > 0.) {
114     stepw = sens*(Bound - parprec)*0.5;
115     param = parprec + sens*stepw;
116   }
117
118   evalpinit(parinit,previousP,parprec,param,
119             infbound,supbound, clasonS1, clasonS2);
120
121   while (!Arrive) {
122
123 #ifdef DEB
124     sectioncalculee = 0;
125     nbcomputedsection++;
126 #endif
127     Standard_Boolean bonpoint = 1;
128     Func.Set(param);
129     rsnld.Perform(Func,parinit,infbound,supbound);
130
131     if (!rsnld.IsDone()) {
132       State = Blend_StepTooLarge;
133       bonpoint = 0;
134     }
135     else {
136       rsnld.Root(sol);
137
138       if(clasonS1) situ1 = domain1->Classify(gp_Pnt2d(sol(1),sol(2)),
139                                              Min(tolerance(1),tolerance(2)),0);
140       else situ1 = TopAbs_IN;
141       if(clasonS2) situ2 = domain2->Classify(gp_Pnt2d(sol(3),sol(4)),
142                                              Min(tolerance(3),tolerance(4)),0);
143       else situ2 = TopAbs_IN;
144     }
145     if(bonpoint && line->NbPoints() == 1 && (situ1 != TopAbs_IN || situ2 != TopAbs_IN)){
146       State = Blend_StepTooLarge;
147       bonpoint = 0;
148     }
149     if(bonpoint){
150       w1 = w2 = Bound;
151       recad1 = Standard_False;
152       recad2 = Standard_False;
153       echecrecad = Standard_False;
154       control = Standard_False;
155
156       if (situ1 == TopAbs_OUT || situ1 == TopAbs_ON) {
157         // pb inverse sur surf1
158         //Si le recadrage s'effectue dans le sens de la progression a une tolerance pres,
159         //on a pris la mauvaise solution.
160         recad1 = Recadre(FuncInv,Standard_True,
161                          sol,solrst1,Index1,Isvtx1,Vtx1);
162
163         if (recad1) {
164           Standard_Real wtemp;
165           wtemp  = solrst1(2);
166           if ((param - wtemp)/sens>= -10*tolesp){
167             w1 = solrst1(2);
168             control = Standard_True;
169           }
170           else {
171             echecrecad = Standard_True;
172             recad1 = Standard_False;
173             State = Blend_StepTooLarge;
174             bonpoint = 0;
175             stepw = stepw/2.;
176           }
177         }
178         else {
179           echecrecad = Standard_True;
180         }
181       }
182       if (situ2 == TopAbs_OUT || situ2 == TopAbs_ON) {
183         // pb inverse sur surf2
184         //Si le recadrage s'effectue dans le sens de la progression a une tolerance pres,
185         //on a pris la mauvaise solution.
186         recad2 = Recadre(FuncInv,Standard_False,
187                          sol,solrst2,Index2,Isvtx2,Vtx2);
188         
189         if (recad2) {
190           Standard_Real wtemp;
191           wtemp = solrst2(2);
192           if ((param - wtemp)/sens>= -10*tolesp){
193             w2 = solrst2(2);
194             control = Standard_True;
195           }
196           else {
197             echecrecad = Standard_True;
198             recad2 = Standard_False;
199             State = Blend_StepTooLarge;
200             bonpoint = 0;
201             stepw = stepw/2.;
202           }
203         }
204         else {
205           echecrecad = Standard_True;
206         }
207       }
208       
209       // Que faut il controler
210       if (recad1 && recad2) {
211           if (Abs(w1-w2) <= 10*tolgui) {
212           // pas besoin de controler les recadrage
213           // Le control pouvant se planter (cf model blend10)
214           // La tolerance est choisie grossse afin, de permetre au 
215           // cheminement suivant, de poser quelques sections ...
216           control = Standard_False; 
217           }
218           else if (sens*(w1-w2) < 0.) {
219             //sol sur 1 ?
220             recad2 = Standard_False;
221           }
222           else {
223             //sol sur 2 ?
224             recad1 = Standard_False;
225           }
226         }
227
228       // Controle effectif des recadrage
229       if (control) {
230         TopAbs_State situ;
231         if (recad1 && clasonS2) {
232           situ = recdomain2->Classify(gp_Pnt2d(solrst1(3),solrst1(4)),
233                                       Min(tolerance(3),tolerance(4)));
234           if (situ == TopAbs_OUT) {
235             recad1 = Standard_False;
236             echecrecad = Standard_True;
237           }
238         }
239         else if (recad2 && clasonS1) {
240           situ = recdomain1->Classify(gp_Pnt2d(solrst2(3),solrst2(4)),
241                                       Min(tolerance(1),tolerance(1)));
242           if (situ == TopAbs_OUT) {
243             recad2 = Standard_False;
244             echecrecad = Standard_True;
245           }
246         }
247       }
248
249       if(recad1 || recad2) echecrecad = Standard_False;
250
251       if (!echecrecad) {
252         if (recad1 && recad2) {
253           //sol sur 1 et 2 a la fois
254           // On passe par les arcs , pour ne pas avoir de probleme
255           // avec les surfaces periodiques.
256           State = Blend_OnRst12;
257           param =  (w1+w2)/2;
258           p2d = TheArcTool::Value(recdomain1->Value(),solrst1(1));
259           sol(1) = p2d.X();
260           sol(2) = p2d.Y();
261           p2d = TheArcTool::Value(recdomain2->Value(),solrst2(1));
262           sol(3) = p2d.X();
263           sol(4) = p2d.Y();
264         }
265         else if (recad1) {
266           // sol sur 1
267           State = Blend_OnRst1;
268           param = w1;
269           recdomain1->Init();
270           nbarc = 1;
271           while (nbarc < Index1) {
272             nbarc++;
273             recdomain1->Next();
274           }
275           p2d = TheArcTool::Value(recdomain1->Value(),solrst1(1));
276           sol(1) = p2d.X();
277           sol(2) = p2d.Y();
278           sol(3) = solrst1(3);
279           sol(4) = solrst1(4);
280         }
281         else if (recad2) {
282           //sol sur 2
283           State = Blend_OnRst2;
284           param = w2;
285           
286           recdomain2->Init();
287           nbarc = 1;
288           while (nbarc < Index2) {
289             nbarc++;
290             recdomain2->Next();
291           }
292           p2d = TheArcTool::Value(recdomain2->Value(),solrst2(1));
293           sol(1) = solrst2(3);
294           sol(2) = solrst2(4);
295           sol(3) = p2d.X();
296           sol(4) = p2d.Y();
297         }
298         else {
299           State = Blend_OK;
300         }
301
302         Standard_Boolean testdefl = 1;
303 #ifdef DEB
304         testdefl = !Blend_GetcontextNOTESTDEFL();
305 #endif  
306         if (recad1 || recad2) {
307           Func.Set(param);
308           // Il vaut mieux un pas non orthodoxe que pas de recadrage!! PMN
309           State = TestArret(Func, State, 
310                             (testdefl && (Abs(stepw) > 3*tolgui)),
311                             Standard_False, Standard_True);
312         }
313         else {
314           State = TestArret(Func, State, testdefl);
315         }
316       }
317       else { 
318         // Ou bien le pas max est mal regle. On divise.
319 //      if(line->NbPoints() == 1) State = Blend_StepTooLarge;
320         if (stepw > 2*tolgui) State = Blend_StepTooLarge;
321         // Sinon echec recadrage. On sort avec PointsConfondus
322         else {
323 #if DEB
324           cout << "Echec recadrage" << endl;
325 #endif    
326           State = Blend_SamePoints;
327         }
328       }
329     }
330
331 #ifdef DEB
332     if (Blend_GettraceDRAWSECT()){
333       Drawsect(surf1,surf2,sol,param,Func, State);
334     }
335 #endif
336     switch (State) {
337     case Blend_OK :
338       {  
339         // Mettre a jour la ligne.
340         if (sens>0.) {
341           line->Append(previousP);
342         }
343         else {
344           line->Prepend(previousP);
345         }
346
347         parprec = param;
348
349         if (param == Bound) {
350           Arrive = Standard_True;
351           Ext1.SetValue(previousP.PointOnS1(),
352                         sol(1),sol(2),
353                         previousP.Parameter(), tolesp);
354           Ext2.SetValue(previousP.PointOnS2(),
355                         sol(3),sol(4),
356                         previousP.Parameter(), tolesp);
357           if (!previousP.IsTangencyPoint()) {
358             Ext1.SetTangent(previousP.TangentOnS1());
359             Ext2.SetTangent(previousP.TangentOnS2());
360           }
361
362           // Indiquer que fin sur Bound.
363         }
364         else {
365           param = param + sens*stepw;
366           if (sens*(param - Bound) > - tolgui) {
367             param = Bound;
368           }
369         }
370         evalpinit(parinit,previousP,parprec,param,
371                   infbound,supbound, clasonS1, clasonS2);
372       }
373       break;
374       
375     case Blend_StepTooLarge :
376       {
377         stepw = stepw/2.;
378         if (Abs(stepw) < tolgui) {
379           Ext1.SetValue(previousP.PointOnS1(),
380                         sol(1),sol(2),
381                         previousP.Parameter(),tolesp);
382           Ext2.SetValue(previousP.PointOnS2(),
383                         sol(3),sol(4),
384                         previousP.Parameter(),tolesp);
385           if (!previousP.IsTangencyPoint()) {
386             Ext1.SetTangent(previousP.TangentOnS1());
387             Ext2.SetTangent(previousP.TangentOnS2());
388           }
389           Arrive = Standard_True;
390           if (line->NbPoints()>=2) {
391             // Indiquer qu on s arrete en cours de cheminement
392           }
393 //        else {
394 //          line->Clear();
395 //        }
396         }
397         else {
398           param = parprec + sens*stepw;  // on ne risque pas de depasser Bound.
399           evalpinit(parinit,previousP,parprec,param,
400                     infbound,supbound, clasonS1, clasonS2);
401         }
402       }
403       break;
404       
405     case Blend_StepTooSmall :
406       {
407         // Mettre a jour la ligne.
408         if (sens>0.) {
409           line->Append(previousP);
410         }
411         else {
412           line->Prepend(previousP);
413         }
414
415         parprec = param;
416
417         stepw = Min(1.5*stepw,pasmax);
418         if (param == Bound) {
419           Arrive = Standard_True;
420           Ext1.SetValue(previousP.PointOnS1(),
421                         sol(1),sol(2),
422                         previousP.Parameter(),tolesp);
423           Ext2.SetValue(previousP.PointOnS2(),
424                         sol(3),sol(4), 
425                         previousP.Parameter(),tolesp);
426           if (!previousP.IsTangencyPoint()) {
427             Ext1.SetTangent(previousP.TangentOnS1());
428             Ext2.SetTangent(previousP.TangentOnS2());
429           }
430           // Indiquer que fin sur Bound.
431         }
432         else {
433           param = param + sens*stepw;
434           if (sens*(param - Bound) > - tolgui) {
435             param = Bound;
436           }
437         }
438         evalpinit(parinit,previousP,parprec,param,
439                   infbound,supbound, clasonS1, clasonS2);
440       }
441       break;
442       
443     case Blend_OnRst1  :
444       {
445         if (sens>0.) {
446           line->Append(previousP);
447         }
448         else {
449           line->Prepend(previousP);
450         }
451         MakeExtremity(Ext1,Standard_True,Index1,
452                       solrst1(1),Isvtx1,Vtx1);
453         // On blinde le cas singulier ou un des recadrage a planter
454         if (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2*tolesp)) {
455           Ext2.SetValue(previousP.PointOnS1(),
456                         sol(3),sol(4),tolesp);
457           if (Isvtx1) MakeSingularExtremity(Ext2, Standard_False, Vtx1);
458         }
459         else {
460           Ext2.SetValue(previousP.PointOnS2(),
461                         sol(3),sol(4),
462                         previousP.Parameter(),tolesp);
463         }
464         Arrive = Standard_True;
465       }
466       break;
467
468     case Blend_OnRst2  :
469       {
470         if (sens>0.) {
471           line->Append(previousP);
472         }
473         else {
474           line->Prepend(previousP);
475         }
476         // On blinde le cas singulier ou un des recadrage a plante
477         if (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2*tolesp)) {
478           Ext1.SetValue(previousP.PointOnS2(),
479                         sol(1),sol(2),tolesp);
480           if (Isvtx2) MakeSingularExtremity(Ext1, Standard_True, Vtx2);
481         }
482         else {
483           Ext1.SetValue(previousP.PointOnS1(),
484                         sol(1),sol(2),
485                         previousP.Parameter(),tolesp);
486         }
487         MakeExtremity(Ext2,Standard_False,Index2,
488                       solrst2(1),Isvtx2,Vtx2);
489         Arrive = Standard_True;
490       }
491       break;
492
493
494     case Blend_OnRst12 :
495       {
496         if (sens>0.) {
497           line->Append(previousP);
498         }
499         else {
500           line->Prepend(previousP);
501         }
502
503         if ( (Isvtx1 != Isvtx2) &&
504             (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2*tolesp)) ) {
505           // On blinde le cas singulier ou un seul recadrage
506           // est reconnu comme vertex.
507           if (Isvtx1) {
508             Isvtx2 = Standard_True;
509             Vtx2 = Vtx1;
510           }
511           else {
512             Isvtx1 = Standard_True;
513             Vtx1 = Vtx2;
514           }
515         }
516
517         MakeExtremity(Ext1,Standard_True,Index1,
518                       solrst1(1),Isvtx1,Vtx1);
519         MakeExtremity(Ext2,Standard_False,Index2,
520                       solrst2(1),Isvtx2,Vtx2);
521         Arrive = Standard_True;
522       }
523       break;
524
525     case Blend_SamePoints :
526       {
527         // On arrete
528 #if DEB
529         cout << " Points confondus dans le cheminement" << endl;
530 #endif
531         Ext1.SetValue(previousP.PointOnS1(),
532                       sol(1),sol(2),
533                       previousP.Parameter(),tolesp);
534         Ext2.SetValue(previousP.PointOnS2(),
535                       sol(3),sol(4),
536                       previousP.Parameter(),tolesp);;
537         if (!previousP.IsTangencyPoint()) {
538           Ext1.SetTangent(previousP.TangentOnS1());
539           Ext2.SetTangent(previousP.TangentOnS2());
540         }
541         Arrive = Standard_True;
542       }
543       break;
544 #ifndef DEB
545     default:
546       break;
547 #endif
548     }
549     if (Arrive) {
550       if (sens > 0.) {
551         line->SetEndPoints(Ext1,Ext2);
552       }
553       else {
554         line->SetStartPoints(Ext1,Ext2);
555
556       }
557     }
558
559   }
560
561 }