0031668: Visualization - WebGL sample doesn't work on Emscripten 1.39
[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                              const Handle(ChFiDS_HElSpine)& HGuide):
20        sol(1,4),surf1(Surf1),surf2(Surf2),
21        ToCorrectOnRst1(Standard_False),ToCorrectOnRst2(Standard_False),
22        done(Standard_False),
23        clasonS1(Standard_True),clasonS2(Standard_True),
24        check2d(Standard_True),check(Standard_True),
25        twistflag1(Standard_False),twistflag2(Standard_False)
26
27 {
28   domain1 = Domain1;
29   domain2 = Domain2;
30   recdomain1 = Domain1;
31   recdomain2 = Domain2;
32   hguide = HGuide;
33 }
34
35 void Blend_Walking::SetDomainsToRecadre(const Handle(TheTopolTool)& Domain1,
36                                         const Handle(TheTopolTool)& Domain2)
37 {
38   recdomain1 = Domain1;
39   recdomain2 = Domain2;
40 }
41
42 void Blend_Walking::AddSingularPoint(const Blend_Point& P) 
43 {
44   if (jalons.Length() == 0) {
45     jalons.Append(P);
46   }
47   else {
48     Standard_Integer ii, jj;
49     Standard_Real tp = P.Parameter(), 
50                   ti=jalons.First().Parameter();
51     for (jj=1, ii=1; ii<=jalons.Length() && tp>ti; ii++) {
52       jj = ii;
53       ti = jalons.Value(jj).Parameter();
54     }
55     if (tp > ti) jalons.InsertAfter(jj, P);
56     else         jalons.InsertBefore(jj, P); 
57   }
58 }
59
60 void Blend_Walking::Perform(Blend_Function& Func,
61                             Blend_FuncInv& FuncInv,
62                             const Standard_Real Pdep,   
63                             const Standard_Real Pmax,
64                             const Standard_Real MaxStep,
65                             const Standard_Real TolGuide,
66                             const math_Vector& ParDep,
67                             const Standard_Real Tolesp,
68                             const Standard_Real Fleche,
69                             const Standard_Boolean Appro)
70 {
71
72   done = Standard_False;
73   iscomplete = Standard_False;
74   comptra = Standard_False;
75   Standard_Boolean doextremities = 1;
76   if(line.IsNull()) line = new TheLine ();
77   else {line->Clear();doextremities = 0;}
78   tolesp = Abs(Tolesp);
79   tolgui = Abs(TolGuide);
80   fleche = Abs(Fleche);
81   rebrou = Standard_False;
82   pasmax = Abs(MaxStep);
83   if (Pmax-Pdep >= 0.) {
84     sens = 1.;
85   }
86   else {
87     sens = -1.;
88   }
89
90   Blend_Status State;
91
92   param = Pdep;
93   Func.Set(param);
94
95   if (Appro) {
96
97     TopAbs_State situ1,situ2;
98     math_Vector tolerance(1,4),infbound(1,4),supbound(1,4);
99     Func.GetTolerance(tolerance,tolesp);
100     Func.GetBounds(infbound,supbound);
101     math_FunctionSetRoot rsnld(Func,tolerance,30);
102
103     rsnld.Perform(Func,ParDep,infbound,supbound);
104     
105     if (!rsnld.IsDone()) {
106       return;
107     }
108     rsnld.Root(sol);
109
110     if(clasonS1) situ1 = domain1->Classify(gp_Pnt2d(sol(1),sol(2)),
111                                            Min(tolerance(1),tolerance(2)),0);
112     else situ1 = TopAbs_IN;
113     if(clasonS2) situ2 = domain2->Classify(gp_Pnt2d(sol(3),sol(4)),
114                                            Min(tolerance(3),tolerance(4)),0);
115     else situ2 = TopAbs_IN;
116
117     if (situ1 != TopAbs_IN || situ2 != TopAbs_IN) {
118       return;
119     }
120   }
121   else {
122     sol = ParDep;
123   }
124
125 #ifdef OCCT_DEBUG
126   sectioncalculee = 0;
127 #endif
128   State = TestArret(Func, Blend_OK, Standard_False);
129   if (State!=Blend_OK) {
130     return;
131   }
132 #ifdef OCCT_DEBUG
133   if (Blend_GettraceDRAWSECT()){
134     Drawsect(surf1,surf2,sol,param,Func);
135   }
136   nbcomputedsection = 1;
137 #endif
138   // Mettre a jour la ligne.
139   //Correct first parameter if needed
140   if (ToCorrectOnRst1 || ToCorrectOnRst2)
141     previousP.SetParameter(CorrectedParam);
142   line->Append(previousP);
143
144   if(doextremities){
145     TheExtremity ptf1 (previousP.PointOnS1(),
146                        sol(1),sol(2),tolesp);
147     TheExtremity ptf2 (previousP.PointOnS2(),
148                        sol(3),sol(4),tolesp);
149     if (!previousP.IsTangencyPoint()) {
150       ptf1.SetTangent(previousP.TangentOnS1());
151       ptf2.SetTangent(previousP.TangentOnS2());
152     }
153     
154     if (sens>0.) {      
155       line->SetStartPoints(ptf1, ptf2);      
156     }
157     else {
158       line->SetEndPoints(ptf1, ptf2);
159     }
160   }
161
162   InternalPerform(Func,FuncInv,Pmax);
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 OCCT_DEBUG
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   Standard_Real CorrectedU = 0., CorrectedV = 0.;
263   gp_Pnt CorrectedPnt;
264
265   Func.GetTolerance(tolerance, tolesp);
266   Func.GetBounds(infbound, supbound);
267   math_FunctionSetRoot rsnld(Func, tolerance, 30);
268
269   rsnld.Perform(Func, ParDep, infbound, supbound);
270
271   if (!rsnld.IsDone())
272   {
273     return Standard_False;
274   }
275   rsnld.Root(sol);
276
277   w1 = w2 = Pmax;
278
279   recad1 = RecOnS1 && Recadre(FuncInv, Standard_True, sol, solrst1,
280                               Index1, Isvtx1, Vtx1, extrapol);
281   if (recad1)
282   {
283     w1 = solrst1(2);
284   }
285
286   recad2 = RecOnS2 && Recadre(FuncInv, Standard_False, sol, solrst2,
287                               Index2, Isvtx2, Vtx2, extrapol);
288   if (recad2)
289   {
290     w2 = solrst2(2);
291   }
292
293   if (!recad1 && !recad2)
294   {
295     return Standard_False;
296   }
297
298   if (recad1 && recad2)
299   {
300     if (Abs(w1 - w2) <= tolgui)
301     {
302       //sol sur 1 et 2 a la fois
303       State = Blend_OnRst12;
304       param = w1;
305       ParSol(1) = solrst2(3);
306       ParSol(2) = solrst2(4);
307       ParSol(3) = solrst1(3);
308       ParSol(4) = solrst1(4);
309     }
310     else if (sens * (w2 - w1) < 0.0)
311     { // on garde le plus grand
312       //sol sur 1
313       State = Blend_OnRst1;
314       param = w1;
315       
316       recdomain1->Init();
317       nbarc = 1;
318       while (nbarc < Index1)
319       {
320         nbarc++;
321         recdomain1->Next();
322       }
323       p2d = TheArcTool::Value(recdomain1->Value(), solrst1(1));
324       ParSol(1) = p2d.X();
325       ParSol(2) = p2d.Y();
326       ParSol(3) = solrst1(3);
327       ParSol(4) = solrst1(4);
328       
329     }
330     else
331     {
332       //sol sur 2
333       State = Blend_OnRst2;
334       param = w2;
335       
336       recdomain2->Init();
337       nbarc = 1;
338       while (nbarc < Index2)
339       {
340         nbarc++;
341         recdomain2->Next();
342       }
343       p2d = TheArcTool::Value(recdomain2->Value(), solrst2(1));
344       ParSol(1) = solrst2(3);
345       ParSol(2) = solrst2(4);
346       ParSol(3) = p2d.X();
347       ParSol(4) = p2d.Y();
348     }
349   }
350   else if (recad1)
351   {
352     // sol sur 1
353     State = Blend_OnRst1;
354     param = w1;
355     recdomain1->Init();
356     nbarc = 1;
357     while (nbarc < Index1)
358     {
359       nbarc++;
360       recdomain1->Next();
361     }
362     p2d = TheArcTool::Value(recdomain1->Value(), solrst1(1));
363     ParSol(1) = p2d.X();
364     ParSol(2) = p2d.Y();
365     ParSol(3) = solrst1(3);
366     ParSol(4) = solrst1(4);
367     gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf1,ParSol(1),ParSol(2));
368     if (CorrectExtremityOnOneRst(1, ParSol(3), ParSol(4), param, thePntOnRst,
369                                  CorrectedU,CorrectedV,CorrectedPnt,CorrectedParam))
370       ToCorrectOnRst1 = Standard_True;
371   }
372   else
373   { //if (recad2) {
374     //sol sur 2
375     State = Blend_OnRst2;
376     param = w2;
377     
378     recdomain2->Init();
379     nbarc = 1;
380     while (nbarc < Index2)
381     {
382       nbarc++;
383       recdomain2->Next();
384     }
385     p2d = TheArcTool::Value(recdomain2->Value(), solrst2(1));
386     ParSol(1) = solrst2(3);
387     ParSol(2) = solrst2(4);
388     ParSol(3) = p2d.X();
389     ParSol(4) = p2d.Y();
390     gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf2,ParSol(3),ParSol(4));
391     if (CorrectExtremityOnOneRst(2, ParSol(1), ParSol(2), param, thePntOnRst,
392                                  CorrectedU,CorrectedV,CorrectedPnt,CorrectedParam))
393       ToCorrectOnRst2 = Standard_True;
394   }
395
396   Psol = param;
397   sol = ParSol;
398   Func.Set(param);
399   State = TestArret(Func, State, Standard_False);
400   switch (State)
401   {
402   case Blend_OnRst1:
403     {
404 #ifdef OCCT_DEBUG
405       if (Blend_GettraceDRAWSECT())
406       {
407         Drawsect(surf1, surf2, sol, param, Func);
408       }
409 #endif
410       MakeExtremity(Ext1, Standard_True, Index1, solrst1(1), Isvtx1, Vtx1);
411       if (ToCorrectOnRst1)
412         Ext2.SetValue(CorrectedPnt, CorrectedU, CorrectedV, tolesp);
413       else
414         Ext2.SetValue(previousP.PointOnS2(), sol(3), sol(4), tolesp);
415     }
416     break;
417
418   case Blend_OnRst2:
419     {
420 #ifdef OCCT_DEBUG
421       if (Blend_GettraceDRAWSECT())
422       {
423         Drawsect(surf1, surf2, sol, param, Func);
424       }
425 #endif
426       if (ToCorrectOnRst2)
427         Ext1.SetValue(CorrectedPnt, CorrectedU, CorrectedV, tolesp);
428       else
429         Ext1.SetValue(previousP.PointOnS1(), sol(1), sol(2), tolesp);
430       MakeExtremity(Ext2, Standard_False, Index2, solrst2(1), Isvtx2, Vtx2);
431     }
432     break;
433
434   case Blend_OnRst12 :
435     {
436       #ifdef OCCT_DEBUG
437       if (Blend_GettraceDRAWSECT())
438       {
439         Drawsect(surf1, surf2, sol, param, Func);
440       }
441       #endif
442       MakeExtremity(Ext1, Standard_True , Index1, solrst1(1), Isvtx1, Vtx1);
443       MakeExtremity(Ext2, Standard_False, Index2, solrst2(1), Isvtx2, Vtx2);
444     }
445     break;
446   default:
447     {
448       throw Standard_Failure("Blend_Walking::PerformFirstSection : echec");
449     }
450   }
451   if (sens < 0.0)
452   {
453     line->SetEndPoints(Ext1, Ext2);
454   }
455   else
456   {
457     line->SetStartPoints(Ext1, Ext2);
458   }
459   return Standard_True;
460 }
461
462
463
464 Standard_Boolean Blend_Walking::Continu(Blend_Function& Func,
465                                         Blend_FuncInv& FuncInv,
466                                         const Standard_Real P)
467 {
468   if (!done) {throw StdFail_NotDone();}
469   const Blend_Point& firstBP =  line->Point(1);
470   const Blend_Point& lastBP =  line->Point(line->NbPoints());
471
472   if (P < firstBP.Parameter()){
473     sens = -1.;
474     previousP = firstBP;
475   }
476   else if(P > lastBP.Parameter()){
477     sens = 1.;
478     previousP = lastBP;
479   }
480
481   param = previousP.Parameter();
482   previousP.ParametersOnS1(sol(1),sol(2));
483   previousP.ParametersOnS2(sol(3),sol(4));
484
485   InternalPerform(Func,FuncInv,P);
486   return Standard_True;
487 }
488
489
490 Standard_Boolean Blend_Walking::Continu(Blend_Function& Func,
491                                         Blend_FuncInv& FuncInv,
492                                         const Standard_Real P,
493                                         const Standard_Boolean OnS1)
494 {
495   if (!done) {throw StdFail_NotDone();}
496   TheExtremity Ext1,Ext2;
497   if (sens < 0.) {
498     Ext1 = line->StartPointOnFirst();
499     Ext2 = line->StartPointOnSecond();
500     if ((OnS1 && Ext1.NbPointOnRst() == 0) ||
501         (!OnS1 && Ext2.NbPointOnRst() == 0)) {
502       return Standard_False;
503     }
504     previousP = line->Point(1);
505
506
507   }
508   else {
509     Ext1 = line->EndPointOnFirst();
510     Ext2 = line->EndPointOnSecond();
511     if ((OnS1 && Ext1.NbPointOnRst() == 0) ||
512         (!OnS1 && Ext2.NbPointOnRst() == 0)) {
513       return Standard_False;
514     }
515     previousP = line->Point(line->NbPoints());
516   }
517
518   Standard_Integer length = line->NbPoints();
519   param = previousP.Parameter();
520   previousP.ParametersOnS1(sol(1),sol(2));
521   previousP.ParametersOnS2(sol(3),sol(4));
522   
523   if(OnS1) clasonS1 = Standard_False;
524   else clasonS2 = Standard_False;
525
526   InternalPerform(Func,FuncInv,P);
527
528   clasonS1 = Standard_True;
529   clasonS2 = Standard_True;
530
531   Standard_Integer newlength = line->NbPoints();
532   if (sens <0.) {
533     if ((OnS1 && line->StartPointOnSecond().NbPointOnRst() == 0) ||
534         (!OnS1 && line->StartPointOnFirst().NbPointOnRst() == 0)) {
535       line->Remove(1,newlength-length);
536       line->SetStartPoints(Ext1,Ext2);
537       return Standard_False;
538     }
539   }
540   else {
541     if ((OnS1 && line->EndPointOnSecond().NbPointOnRst() == 0) ||
542         (!OnS1 && line->EndPointOnFirst().NbPointOnRst() == 0)) {
543       line->Remove(length,newlength);
544       line->SetEndPoints(Ext1,Ext2);
545       return Standard_False;
546     }
547   }
548   return Standard_True;
549 }
550
551
552 Standard_Boolean Blend_Walking::Complete(Blend_Function& Func,
553                                          Blend_FuncInv& FuncInv,
554                                          const Standard_Real Pmin)
555 {
556   if (!done) {throw StdFail_NotDone();}
557   if (iscomplete) {return Standard_True;}
558
559   if (sens >0.) {
560     previousP = line->Point(1);
561   }
562   else {
563     previousP = line->Point(line->NbPoints());
564   }
565
566   sens = -sens;
567
568   param = previousP.Parameter();
569   previousP.ParametersOnS1(sol(1),sol(2));
570   previousP.ParametersOnS2(sol(3),sol(4));
571
572   InternalPerform(Func,FuncInv,Pmin);
573
574   iscomplete = Standard_True;
575   return Standard_True;
576 }
577
578 void Blend_Walking::ClassificationOnS1(const Standard_Boolean C)
579 {
580   clasonS1 = C;
581 }
582
583 void Blend_Walking::ClassificationOnS2(const Standard_Boolean C)
584 {
585   clasonS2 = C;
586 }
587
588 void Blend_Walking::Check2d(const Standard_Boolean C)
589 {
590   check2d = C;
591 }
592
593 void Blend_Walking::Check(const Standard_Boolean C)
594 {
595   check = C;
596 }