c082938705095da5114f16835b71a0f12993c705
[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
169 (Blend_Function&     Func,
170  const Standard_Real Pdep,   
171  math_Vector&        ParDep,
172  const Standard_Real Tolesp,
173  const Standard_Real TolGuide,
174  TopAbs_State&       Pos1,
175  TopAbs_State&       Pos2)
176 {
177   iscomplete = Standard_False;
178   comptra = Standard_False;
179   line = new TheLine ();
180   tolesp = Abs(Tolesp);
181   tolgui = Abs(TolGuide);
182
183   Pos1 = Pos2 = TopAbs_UNKNOWN;
184
185   Blend_Status State;
186
187   param = Pdep;
188   Func.Set(param);
189
190   math_Vector tolerance(1,4),infbound(1,4),supbound(1,4);
191   Func.GetTolerance(tolerance,tolesp);
192   Func.GetBounds(infbound,supbound);
193   math_FunctionSetRoot rsnld(Func,tolerance,30);
194   
195   rsnld.Perform(Func,ParDep,infbound,supbound);
196   
197   if (!rsnld.IsDone()) {
198     return Standard_False;
199   }
200   rsnld.Root(sol);
201   ParDep = sol;
202   Pos1 = domain1->Classify(gp_Pnt2d(sol(1),sol(2)),
203                            Min(tolerance(1),tolerance(2)),0);
204   Pos2 = domain2->Classify(gp_Pnt2d(sol(3),sol(4)),
205                            Min(tolerance(3),tolerance(4)),0);
206   if (Pos1 != TopAbs_IN || Pos2 != TopAbs_IN) {
207     return Standard_False;
208   }
209
210   State = TestArret(Func, Blend_OK, Standard_False);
211 #ifdef DEB
212   if (Blend_GettraceDRAWSECT()){
213     Drawsect(surf1,surf2,sol,param,Func);
214   }
215 #endif
216   return Standard_True;
217 }
218
219
220 Standard_Boolean Blend_Walking::PerformFirstSection
221    (Blend_Function& Func,
222     Blend_FuncInv& FuncInv,
223     const Standard_Real Pdep,   
224     const Standard_Real Pmax,   
225     const math_Vector& ParDep,
226     const Standard_Real Tolesp,
227     const Standard_Real TolGuide,
228     const Standard_Boolean RecOnS1,
229     const Standard_Boolean RecOnS2,
230     Standard_Real& Psol,   
231     math_Vector& ParSol)
232
233 {
234   iscomplete = Standard_False;
235   comptra = Standard_False;
236   line = new TheLine ();
237
238   Standard_Real w1,w2, extrapol;
239   Standard_Boolean recad1,recad2;
240
241   tolesp = Abs(Tolesp);
242   tolgui = Abs(TolGuide);
243   if (Pmax-Pdep >= 0.) {
244     sens = 1.;
245   }
246   else {
247     sens = -1.;
248   }
249   extrapol = Abs(Pmax-Pdep)/50; // 2%
250
251   Blend_Status State;
252
253   param = Pdep;
254   Func.Set(param);
255
256   math_Vector tolerance(1,4),infbound(1,4),supbound(1,4);
257   math_Vector solrst1(1,4),solrst2(1,4);
258   TheExtremity Ext1,Ext2;
259   Standard_Integer Index1 = 0, Index2 = 0, nbarc;
260   Standard_Boolean Isvtx1 = Standard_False, Isvtx2 = Standard_False;
261   TheVertex Vtx1,Vtx2;
262   gp_Pnt2d p2d;
263
264   Func.GetTolerance(tolerance,tolesp);
265   Func.GetBounds(infbound,supbound);
266   math_FunctionSetRoot rsnld(Func,tolerance,30);
267
268   rsnld.Perform(Func,ParDep,infbound,supbound);
269     
270   if (!rsnld.IsDone()) {
271     return Standard_False;
272   }
273   rsnld.Root(sol);
274
275   w1 = w2 = Pmax;
276
277   recad1 = RecOnS1 && Recadre(FuncInv,Standard_True,
278                               sol,solrst1,Index1,Isvtx1,Vtx1, extrapol);
279   if (recad1) {
280     w1 = solrst1(2);
281   }
282
283   recad2 = RecOnS2 && Recadre(FuncInv,Standard_False,
284                               sol,solrst2,Index2,Isvtx2,Vtx2, extrapol);
285   if (recad2) {
286     w2 = solrst2(2);
287   }
288
289   if (!recad1 && !recad2) {
290     return Standard_False;
291   }
292
293   if (recad1 && recad2) {
294     if (Abs(w1-w2) <= tolgui) {
295       //sol sur 1 et 2 a la fois
296       State = Blend_OnRst12;
297       param = w1;
298       ParSol(1) = solrst2(3);
299       ParSol(2) = solrst2(4);
300       ParSol(3) = solrst1(3);
301       ParSol(4) = solrst1(4);
302     }
303     else if (sens*(w2-w1) < 0.) { // on garde le plus grand
304       //sol sur 1
305       State = Blend_OnRst1;
306       param = w1;
307       
308       recdomain1->Init();
309       nbarc = 1;
310       while (nbarc < Index1) {
311         nbarc++;
312         recdomain1->Next();
313       }
314       p2d = TheArcTool::Value(recdomain1->Value(),solrst1(1));
315       ParSol(1) = p2d.X();
316       ParSol(2) = p2d.Y();
317       ParSol(3) = solrst1(3);
318       ParSol(4) = solrst1(4);
319       
320     }
321     else {
322       //sol sur 2
323       State = Blend_OnRst2;
324       param = w2;
325       
326       recdomain2->Init();
327       nbarc = 1;
328       while (nbarc < Index2) {
329         nbarc++;
330         recdomain2->Next();
331       }
332       p2d = TheArcTool::Value(recdomain2->Value(),solrst2(1));
333       ParSol(1) = solrst2(3);
334       ParSol(2) = solrst2(4);
335       ParSol(3) = p2d.X();
336       ParSol(4) = p2d.Y();
337     }
338   }
339   else if (recad1) {
340     // sol sur 1
341     State = Blend_OnRst1;
342     param = w1;
343     recdomain1->Init();
344     nbarc = 1;
345     while (nbarc < Index1) {
346       nbarc++;
347       recdomain1->Next();
348     }
349     p2d = TheArcTool::Value(recdomain1->Value(),solrst1(1));
350     ParSol(1) = p2d.X();
351     ParSol(2) = p2d.Y();
352     ParSol(3) = solrst1(3);
353     ParSol(4) = solrst1(4);
354   }
355   else { //if (recad2) {
356     //sol sur 2
357     State = Blend_OnRst2;
358     param = w2;
359     
360     recdomain2->Init();
361     nbarc = 1;
362     while (nbarc < Index2) {
363       nbarc++;
364       recdomain2->Next();
365     }
366     p2d = TheArcTool::Value(recdomain2->Value(),solrst2(1));
367     ParSol(1) = solrst2(3);
368     ParSol(2) = solrst2(4);
369     ParSol(3) = p2d.X();
370     ParSol(4) = p2d.Y();
371   }
372
373   Psol = param;
374   sol = ParSol;
375   Func.Set(param);
376   State = TestArret(Func, State, Standard_False);
377   switch (State) {
378   case Blend_OnRst1  :
379     {
380 #ifdef DEB
381       if (Blend_GettraceDRAWSECT()){
382         Drawsect(surf1,surf2,sol,param,Func);
383       }
384 #endif
385       MakeExtremity(Ext1,Standard_True,Index1,
386                     solrst1(1),Isvtx1,Vtx1);
387       Ext2.SetValue(previousP.PointOnS2(),
388                     sol(3),sol(4),tolesp);
389     }
390     break;
391     
392   case Blend_OnRst2  :
393     {
394 #ifdef DEB
395       if (Blend_GettraceDRAWSECT()){
396         Drawsect(surf1,surf2,sol,param,Func);
397       }
398 #endif
399       Ext1.SetValue(previousP.PointOnS1(),
400                     sol(1),sol(2),tolesp);
401       MakeExtremity(Ext2,Standard_False,Index2,
402                     solrst2(1),Isvtx2,Vtx2);
403     }
404     break;
405     
406   case Blend_OnRst12 :
407     {
408 #ifdef DEB
409       if (Blend_GettraceDRAWSECT()){
410         Drawsect(surf1,surf2,sol,param,Func);
411       }
412 #endif
413       MakeExtremity(Ext1,Standard_True,Index1,
414                     solrst1(1),Isvtx1,Vtx1);
415       MakeExtremity(Ext2,Standard_False,Index2,
416                     solrst2(1),Isvtx2,Vtx2);
417     }
418     break;
419   default:
420     {
421       Standard_Failure::Raise("Blend_Walking::PerformFirstSection : echec");
422     }
423   }
424   if (sens < 0.) {
425     line->SetEndPoints(Ext1,Ext2);
426   }
427   else {
428     line->SetStartPoints(Ext1,Ext2);
429   }
430   return Standard_True;
431 }
432
433
434
435 Standard_Boolean Blend_Walking::Continu(Blend_Function& Func,
436                                         Blend_FuncInv& FuncInv,
437                                         const Standard_Real P)
438 {
439   if (!done) {StdFail_NotDone::Raise();}
440   const Blend_Point& firstBP =  line->Point(1);
441   const Blend_Point& lastBP =  line->Point(line->NbPoints());
442
443   if (P < firstBP.Parameter()){
444     sens = -1.;
445     previousP = firstBP;
446   }
447   else if(P > lastBP.Parameter()){
448     sens = 1.;
449     previousP = lastBP;
450   }
451
452   param = previousP.Parameter();
453   previousP.ParametersOnS1(sol(1),sol(2));
454   previousP.ParametersOnS2(sol(3),sol(4));
455
456   InternalPerform(Func,FuncInv,P);
457   return Standard_True;
458 }
459
460
461 Standard_Boolean Blend_Walking::Continu(Blend_Function& Func,
462                                         Blend_FuncInv& FuncInv,
463                                         const Standard_Real P,
464                                         const Standard_Boolean OnS1)
465 {
466   if (!done) {StdFail_NotDone::Raise();}
467   TheExtremity Ext1,Ext2;
468   if (sens < 0.) {
469     Ext1 = line->StartPointOnFirst();
470     Ext2 = line->StartPointOnSecond();
471     if ((OnS1 && Ext1.NbPointOnRst() == 0) ||
472         (!OnS1 && Ext2.NbPointOnRst() == 0)) {
473       return Standard_False;
474     }
475     previousP = line->Point(1);
476
477
478   }
479   else {
480     Ext1 = line->EndPointOnFirst();
481     Ext2 = line->EndPointOnSecond();
482     if ((OnS1 && Ext1.NbPointOnRst() == 0) ||
483         (!OnS1 && Ext2.NbPointOnRst() == 0)) {
484       return Standard_False;
485     }
486     previousP = line->Point(line->NbPoints());
487   }
488
489   Standard_Integer length = line->NbPoints();
490   param = previousP.Parameter();
491   previousP.ParametersOnS1(sol(1),sol(2));
492   previousP.ParametersOnS2(sol(3),sol(4));
493   
494   if(OnS1) clasonS1 = Standard_False;
495   else clasonS2 = Standard_False;
496
497   InternalPerform(Func,FuncInv,P);
498
499   clasonS1 = Standard_True;
500   clasonS2 = Standard_True;
501
502   Standard_Integer newlength = line->NbPoints();
503   if (sens <0.) {
504     if ((OnS1 && line->StartPointOnSecond().NbPointOnRst() == 0) ||
505         (!OnS1 && line->StartPointOnFirst().NbPointOnRst() == 0)) {
506       line->Remove(1,newlength-length);
507       line->SetStartPoints(Ext1,Ext2);
508       return Standard_False;
509     }
510   }
511   else {
512     if ((OnS1 && line->EndPointOnSecond().NbPointOnRst() == 0) ||
513         (!OnS1 && line->EndPointOnFirst().NbPointOnRst() == 0)) {
514       line->Remove(length,newlength);
515       line->SetEndPoints(Ext1,Ext2);
516       return Standard_False;
517     }
518   }
519   return Standard_True;
520 }
521
522
523 Standard_Boolean Blend_Walking::Complete(Blend_Function& Func,
524                                          Blend_FuncInv& FuncInv,
525                                          const Standard_Real Pmin)
526 {
527   if (!done) {StdFail_NotDone::Raise();}
528   if (iscomplete) {return Standard_True;}
529
530   if (sens >0.) {
531     previousP = line->Point(1);
532   }
533   else {
534     previousP = line->Point(line->NbPoints());
535   }
536
537   sens = -sens;
538
539   param = previousP.Parameter();
540   previousP.ParametersOnS1(sol(1),sol(2));
541   previousP.ParametersOnS2(sol(3),sol(4));
542
543   InternalPerform(Func,FuncInv,Pmin);
544
545 #ifdef DEB
546 //  cout <<"Complete : "<<nbcomputedsection<<" sections calculees"<<endl;
547 //  cout <<line->NbPoints()<<" sections gardees"<<endl;
548 #endif
549
550   iscomplete = Standard_True;
551   return Standard_True;
552 }
553
554 void Blend_Walking::ClassificationOnS1(const Standard_Boolean C)
555 {
556   clasonS1 = C;
557 }
558
559 void Blend_Walking::ClassificationOnS2(const Standard_Boolean C)
560 {
561   clasonS2 = C;
562 }
563
564 void Blend_Walking::Check2d(const Standard_Boolean C)
565 {
566   check2d = C;
567 }
568
569 void Blend_Walking::Check(const Standard_Boolean C)
570 {
571   check = C;
572 }
573