0024513: Suspicious code highlighted by 0024510
[occt.git] / src / Blend / Blend_Walking_1.gxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 Blend_Walking::Blend_Walking(const TheSurface& Surf1,
16                              const TheSurface& Surf2,
17                              const Handle(TheTopolTool)& Domain1,
18                              const Handle(TheTopolTool)& Domain2):
19        sol(1,4),surf1(Surf1),surf2(Surf2),
20        done(Standard_False),
21        clasonS1(Standard_True),clasonS2(Standard_True),
22        check2d(Standard_True),check(Standard_True),
23        twistflag1(Standard_False),twistflag2(Standard_False)
24
25 {
26   domain1 = Domain1;
27   domain2 = Domain2;
28   recdomain1 = Domain1;
29   recdomain2 = Domain2;  
30 }
31
32 void Blend_Walking::SetDomainsToRecadre(const Handle(TheTopolTool)& Domain1,
33                                         const Handle(TheTopolTool)& Domain2)
34 {
35   recdomain1 = Domain1;
36   recdomain2 = Domain2;
37 }
38
39 void Blend_Walking::AddSingularPoint(const Blend_Point& P) 
40 {
41   if (jalons.Length() == 0) {
42     jalons.Append(P);
43   }
44   else {
45     Standard_Integer ii, jj;
46     Standard_Real tp = P.Parameter(), 
47                   ti=jalons.First().Parameter();
48     for (jj=1, ii=1; ii<=jalons.Length() && tp>ti; ii++) {
49       jj = ii;
50       ti = jalons.Value(jj).Parameter();
51     }
52     if (tp > ti) jalons.InsertAfter(jj, P);
53     else         jalons.InsertBefore(jj, P); 
54   }
55 }
56
57 void Blend_Walking::Perform(Blend_Function& Func,
58                             Blend_FuncInv& FuncInv,
59                             const Standard_Real Pdep,   
60                             const Standard_Real Pmax,
61                             const Standard_Real MaxStep,
62                             const Standard_Real TolGuide,
63                             const math_Vector& ParDep,
64                             const Standard_Real Tolesp,
65                             const Standard_Real Fleche,
66                             const Standard_Boolean Appro)
67 {
68
69   done = Standard_False;
70   iscomplete = Standard_False;
71   comptra = Standard_False;
72   Standard_Boolean doextremities = 1;
73   if(line.IsNull()) line = new TheLine ();
74   else {line->Clear();doextremities = 0;}
75   tolesp = Abs(Tolesp);
76   tolgui = Abs(TolGuide);
77   fleche = Abs(Fleche);
78   rebrou = Standard_False;
79   pasmax = Abs(MaxStep);
80   if (Pmax-Pdep >= 0.) {
81     sens = 1.;
82   }
83   else {
84     sens = -1.;
85   }
86
87   Blend_Status State;
88   TheExtremity ptf1,ptf2;
89
90   param = Pdep;
91   Func.Set(param);
92
93   if (Appro) {
94
95     TopAbs_State situ1,situ2;
96     math_Vector tolerance(1,4),infbound(1,4),supbound(1,4);
97     Func.GetTolerance(tolerance,tolesp);
98     Func.GetBounds(infbound,supbound);
99     math_FunctionSetRoot rsnld(Func,tolerance,30);
100
101     rsnld.Perform(Func,ParDep,infbound,supbound);
102     
103     if (!rsnld.IsDone()) {
104       return;
105     }
106     rsnld.Root(sol);
107
108     if(clasonS1) situ1 = domain1->Classify(gp_Pnt2d(sol(1),sol(2)),
109                                            Min(tolerance(1),tolerance(2)),0);
110     else situ1 = TopAbs_IN;
111     if(clasonS2) situ2 = domain2->Classify(gp_Pnt2d(sol(3),sol(4)),
112                                            Min(tolerance(3),tolerance(4)),0);
113     else situ2 = TopAbs_IN;
114
115     if (situ1 != TopAbs_IN || situ2 != TopAbs_IN) {
116       return;
117     }
118   }
119   else {
120     sol = ParDep;
121   }
122
123 #ifdef DEB
124   sectioncalculee = 0;
125 #endif
126   State = TestArret(Func, Blend_OK, Standard_False);
127   if (State!=Blend_OK) {
128     return;
129   }
130 #ifdef DEB
131   if (Blend_GettraceDRAWSECT()){
132     Drawsect(surf1,surf2,sol,param,Func);
133   }
134   nbcomputedsection = 1;
135 #endif
136   // Mettre a jour la ligne.
137   line->Append(previousP);
138
139   if(doextremities){
140     TheExtremity ptf1 (previousP.PointOnS1(),
141                        sol(1),sol(2),tolesp);
142     TheExtremity ptf2 (previousP.PointOnS2(),
143                        sol(3),sol(4),tolesp);
144     if (!previousP.IsTangencyPoint()) {
145       ptf1.SetTangent(previousP.TangentOnS1());
146       ptf2.SetTangent(previousP.TangentOnS2());
147     }
148     
149     if (sens>0.) {      
150       line->SetStartPoints(ptf1, ptf2);      
151     }
152     else {
153       line->SetEndPoints(ptf1, ptf2);
154     }
155   }
156
157   InternalPerform(Func,FuncInv,Pmax);
158
159 #ifdef DEB
160 //  cout <<"Perform : "<<nbcomputedsection<<" sections calculees"<<endl;
161 //  cout <<line->NbPoints()<<" sections gardees"<<endl;
162 #endif
163
164   done = Standard_True;
165 }
166
167
168 Standard_Boolean Blend_Walking::PerformFirstSection(Blend_Function&     Func,
169                                                     const Standard_Real Pdep,
170                                                     math_Vector&        ParDep,
171                                                     const Standard_Real Tolesp,
172                                                     const Standard_Real TolGuide,
173                                                     TopAbs_State&       Pos1,
174                                                     TopAbs_State&       Pos2)
175 {
176   iscomplete = Standard_False;
177   comptra = Standard_False;
178   line = new TheLine ();
179   tolesp = Abs(Tolesp);
180   tolgui = Abs(TolGuide);
181
182   Pos1 = Pos2 = TopAbs_UNKNOWN;
183
184   param = Pdep;
185   Func.Set(param);
186
187   math_Vector tolerance(1, 4),infbound(1, 4),supbound(1, 4);
188   Func.GetTolerance(tolerance, tolesp);
189   Func.GetBounds(infbound, supbound);
190   math_FunctionSetRoot rsnld(Func, tolerance, 30);
191
192   rsnld.Perform(Func, ParDep, infbound, supbound);
193
194   if (!rsnld.IsDone())
195   {
196     return Standard_False;
197   }
198   rsnld.Root(sol);
199   ParDep = sol;
200   Pos1 = domain1->Classify(gp_Pnt2d(sol(1), sol(2)), Min(tolerance(1), tolerance(2)), 0);
201   Pos2 = domain2->Classify(gp_Pnt2d(sol(3), sol(4)), Min(tolerance(3), tolerance(4)), 0);
202   if (Pos1 != TopAbs_IN || Pos2 != TopAbs_IN)
203   {
204     return Standard_False;
205   }
206
207   TestArret(Func, Blend_OK, Standard_False);
208   #ifdef DEB
209     if (Blend_GettraceDRAWSECT())
210     {
211      Drawsect(surf1, surf2, sol, param, Func);
212     }
213   #endif
214   return Standard_True;
215 }
216
217
218 Standard_Boolean Blend_Walking::PerformFirstSection (Blend_Function& Func,
219                                                      Blend_FuncInv& FuncInv,
220                                                      const Standard_Real Pdep,
221                                                      const Standard_Real Pmax,
222                                                      const math_Vector& ParDep,
223                                                      const Standard_Real Tolesp,
224                                                      const Standard_Real TolGuide,
225                                                      const Standard_Boolean RecOnS1,
226                                                      const Standard_Boolean RecOnS2,
227                                                      Standard_Real& Psol,
228                                                      math_Vector& ParSol)
229
230 {
231   iscomplete = Standard_False;
232   comptra = Standard_False;
233   line = new TheLine ();
234
235   Standard_Real w1, w2, extrapol;
236   Standard_Boolean recad1, recad2;
237
238   tolesp = Abs(Tolesp);
239   tolgui = Abs(TolGuide);
240   if (Pmax - Pdep >= 0.0)
241   {
242     sens = 1.;
243   }
244   else
245   {
246     sens = -1.;
247   }
248   extrapol = Abs(Pmax - Pdep) / 50.0; // 2%
249
250   Blend_Status State;
251
252   param = Pdep;
253   Func.Set(param);
254
255   math_Vector tolerance(1, 4),infbound(1, 4),supbound(1, 4);
256   math_Vector solrst1(1, 4),solrst2(1, 4);
257   TheExtremity Ext1, Ext2;
258   Standard_Integer Index1 = 0, Index2 = 0, nbarc;
259   Standard_Boolean Isvtx1 = Standard_False, Isvtx2 = Standard_False;
260   TheVertex Vtx1, Vtx2;
261   gp_Pnt2d p2d;
262
263   Func.GetTolerance(tolerance, tolesp);
264   Func.GetBounds(infbound, supbound);
265   math_FunctionSetRoot rsnld(Func, tolerance, 30);
266
267   rsnld.Perform(Func, ParDep, infbound, supbound);
268
269   if (!rsnld.IsDone())
270   {
271     return Standard_False;
272   }
273   rsnld.Root(sol);
274
275   w1 = w2 = Pmax;
276
277   recad1 = RecOnS1 && Recadre(FuncInv, Standard_True, sol, solrst1,
278                               Index1, Isvtx1, Vtx1, extrapol);
279   if (recad1)
280   {
281     w1 = solrst1(2);
282   }
283
284   recad2 = RecOnS2 && Recadre(FuncInv, Standard_False, sol, solrst2,
285                               Index2, Isvtx2, Vtx2, extrapol);
286   if (recad2)
287   {
288     w2 = solrst2(2);
289   }
290
291   if (!recad1 && !recad2)
292   {
293     return Standard_False;
294   }
295
296   if (recad1 && recad2)
297   {
298     if (Abs(w1 - w2) <= tolgui)
299     {
300       //sol sur 1 et 2 a la fois
301       State = Blend_OnRst12;
302       param = w1;
303       ParSol(1) = solrst2(3);
304       ParSol(2) = solrst2(4);
305       ParSol(3) = solrst1(3);
306       ParSol(4) = solrst1(4);
307     }
308     else if (sens * (w2 - w1) < 0.0)
309     { // on garde le plus grand
310       //sol sur 1
311       State = Blend_OnRst1;
312       param = w1;
313       
314       recdomain1->Init();
315       nbarc = 1;
316       while (nbarc < Index1)
317       {
318         nbarc++;
319         recdomain1->Next();
320       }
321       p2d = TheArcTool::Value(recdomain1->Value(), solrst1(1));
322       ParSol(1) = p2d.X();
323       ParSol(2) = p2d.Y();
324       ParSol(3) = solrst1(3);
325       ParSol(4) = solrst1(4);
326       
327     }
328     else
329     {
330       //sol sur 2
331       State = Blend_OnRst2;
332       param = w2;
333       
334       recdomain2->Init();
335       nbarc = 1;
336       while (nbarc < Index2)
337       {
338         nbarc++;
339         recdomain2->Next();
340       }
341       p2d = TheArcTool::Value(recdomain2->Value(), solrst2(1));
342       ParSol(1) = solrst2(3);
343       ParSol(2) = solrst2(4);
344       ParSol(3) = p2d.X();
345       ParSol(4) = p2d.Y();
346     }
347   }
348   else if (recad1)
349   {
350     // sol sur 1
351     State = Blend_OnRst1;
352     param = w1;
353     recdomain1->Init();
354     nbarc = 1;
355     while (nbarc < Index1)
356     {
357       nbarc++;
358       recdomain1->Next();
359     }
360     p2d = TheArcTool::Value(recdomain1->Value(), solrst1(1));
361     ParSol(1) = p2d.X();
362     ParSol(2) = p2d.Y();
363     ParSol(3) = solrst1(3);
364     ParSol(4) = solrst1(4);
365   }
366   else
367   { //if (recad2) {
368     //sol sur 2
369     State = Blend_OnRst2;
370     param = w2;
371     
372     recdomain2->Init();
373     nbarc = 1;
374     while (nbarc < Index2)
375     {
376       nbarc++;
377       recdomain2->Next();
378     }
379     p2d = TheArcTool::Value(recdomain2->Value(), solrst2(1));
380     ParSol(1) = solrst2(3);
381     ParSol(2) = solrst2(4);
382     ParSol(3) = p2d.X();
383     ParSol(4) = p2d.Y();
384   }
385
386   Psol = param;
387   sol = ParSol;
388   Func.Set(param);
389   State = TestArret(Func, State, Standard_False);
390   switch (State)
391   {
392   case Blend_OnRst1:
393     {
394       #ifdef DEB
395         if (Blend_GettraceDRAWSECT())
396         {
397           Drawsect(surf1, surf2, sol, param, Func);
398         }
399       #endif
400       MakeExtremity(Ext1, Standard_True, Index1, solrst1(1), Isvtx1, Vtx1);
401       Ext2.SetValue(previousP.PointOnS2(), sol(3), sol(4), tolesp);
402     }
403     break;
404
405   case Blend_OnRst2:
406     {
407       #ifdef DEB
408         if (Blend_GettraceDRAWSECT())
409         {
410           Drawsect(surf1, surf2, sol, param, Func);
411         }
412       #endif
413       Ext1.SetValue(previousP.PointOnS1(), sol(1), sol(2), tolesp);
414       MakeExtremity(Ext2, Standard_False, Index2, solrst2(1), Isvtx2, Vtx2);
415     }
416     break;
417
418   case Blend_OnRst12 :
419     {
420       #ifdef DEB
421       if (Blend_GettraceDRAWSECT())
422       {
423         Drawsect(surf1, surf2, sol, param, Func);
424       }
425       #endif
426       MakeExtremity(Ext1, Standard_True , Index1, solrst1(1), Isvtx1, Vtx1);
427       MakeExtremity(Ext2, Standard_False, Index2, solrst2(1), Isvtx2, Vtx2);
428     }
429     break;
430   default:
431     {
432       Standard_Failure::Raise("Blend_Walking::PerformFirstSection : echec");
433     }
434   }
435   if (sens < 0.0)
436   {
437     line->SetEndPoints(Ext1, Ext2);
438   }
439   else
440   {
441     line->SetStartPoints(Ext1, Ext2);
442   }
443   return Standard_True;
444 }
445
446
447
448 Standard_Boolean Blend_Walking::Continu(Blend_Function& Func,
449                                         Blend_FuncInv& FuncInv,
450                                         const Standard_Real P)
451 {
452   if (!done) {StdFail_NotDone::Raise();}
453   const Blend_Point& firstBP =  line->Point(1);
454   const Blend_Point& lastBP =  line->Point(line->NbPoints());
455
456   if (P < firstBP.Parameter()){
457     sens = -1.;
458     previousP = firstBP;
459   }
460   else if(P > lastBP.Parameter()){
461     sens = 1.;
462     previousP = lastBP;
463   }
464
465   param = previousP.Parameter();
466   previousP.ParametersOnS1(sol(1),sol(2));
467   previousP.ParametersOnS2(sol(3),sol(4));
468
469   InternalPerform(Func,FuncInv,P);
470   return Standard_True;
471 }
472
473
474 Standard_Boolean Blend_Walking::Continu(Blend_Function& Func,
475                                         Blend_FuncInv& FuncInv,
476                                         const Standard_Real P,
477                                         const Standard_Boolean OnS1)
478 {
479   if (!done) {StdFail_NotDone::Raise();}
480   TheExtremity Ext1,Ext2;
481   if (sens < 0.) {
482     Ext1 = line->StartPointOnFirst();
483     Ext2 = line->StartPointOnSecond();
484     if ((OnS1 && Ext1.NbPointOnRst() == 0) ||
485         (!OnS1 && Ext2.NbPointOnRst() == 0)) {
486       return Standard_False;
487     }
488     previousP = line->Point(1);
489
490
491   }
492   else {
493     Ext1 = line->EndPointOnFirst();
494     Ext2 = line->EndPointOnSecond();
495     if ((OnS1 && Ext1.NbPointOnRst() == 0) ||
496         (!OnS1 && Ext2.NbPointOnRst() == 0)) {
497       return Standard_False;
498     }
499     previousP = line->Point(line->NbPoints());
500   }
501
502   Standard_Integer length = line->NbPoints();
503   param = previousP.Parameter();
504   previousP.ParametersOnS1(sol(1),sol(2));
505   previousP.ParametersOnS2(sol(3),sol(4));
506   
507   if(OnS1) clasonS1 = Standard_False;
508   else clasonS2 = Standard_False;
509
510   InternalPerform(Func,FuncInv,P);
511
512   clasonS1 = Standard_True;
513   clasonS2 = Standard_True;
514
515   Standard_Integer newlength = line->NbPoints();
516   if (sens <0.) {
517     if ((OnS1 && line->StartPointOnSecond().NbPointOnRst() == 0) ||
518         (!OnS1 && line->StartPointOnFirst().NbPointOnRst() == 0)) {
519       line->Remove(1,newlength-length);
520       line->SetStartPoints(Ext1,Ext2);
521       return Standard_False;
522     }
523   }
524   else {
525     if ((OnS1 && line->EndPointOnSecond().NbPointOnRst() == 0) ||
526         (!OnS1 && line->EndPointOnFirst().NbPointOnRst() == 0)) {
527       line->Remove(length,newlength);
528       line->SetEndPoints(Ext1,Ext2);
529       return Standard_False;
530     }
531   }
532   return Standard_True;
533 }
534
535
536 Standard_Boolean Blend_Walking::Complete(Blend_Function& Func,
537                                          Blend_FuncInv& FuncInv,
538                                          const Standard_Real Pmin)
539 {
540   if (!done) {StdFail_NotDone::Raise();}
541   if (iscomplete) {return Standard_True;}
542
543   if (sens >0.) {
544     previousP = line->Point(1);
545   }
546   else {
547     previousP = line->Point(line->NbPoints());
548   }
549
550   sens = -sens;
551
552   param = previousP.Parameter();
553   previousP.ParametersOnS1(sol(1),sol(2));
554   previousP.ParametersOnS2(sol(3),sol(4));
555
556   InternalPerform(Func,FuncInv,Pmin);
557
558 #ifdef DEB
559 //  cout <<"Complete : "<<nbcomputedsection<<" sections calculees"<<endl;
560 //  cout <<line->NbPoints()<<" sections gardees"<<endl;
561 #endif
562
563   iscomplete = Standard_True;
564   return Standard_True;
565 }
566
567 void Blend_Walking::ClassificationOnS1(const Standard_Boolean C)
568 {
569   clasonS1 = C;
570 }
571
572 void Blend_Walking::ClassificationOnS2(const Standard_Boolean C)
573 {
574   clasonS2 = C;
575 }
576
577 void Blend_Walking::Check2d(const Standard_Boolean C)
578 {
579   check2d = C;
580 }
581
582 void Blend_Walking::Check(const Standard_Boolean C)
583 {
584   check = C;
585 }