0024048: "Basic Runtime Checks" option of VS projects should be equal to "RTC1"
[occt.git] / src / Blend / Blend_Walking_3.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 //26-04-1997 modified by pmn : Initialisation plus fine de la resolution
20
21 Standard_Integer Blend_Walking::ArcToRecadre(const Standard_Boolean OnFirst,
22                                              const math_Vector& sol,
23                                              const Standard_Integer PrevIndex,
24                                              gp_Pnt2d& lastpt2d,
25                                              gp_Pnt2d& pt2d,
26                                              Standard_Real& ponarc)
27 {
28   Standard_Integer IndexSol = 0,  nbarc = 0;
29   Standard_Boolean ok = Standard_False;
30   Standard_Boolean byinter = (line->NbPoints() != 0), okinter = 0;
31   Standard_Real distmin = RealLast();
32   Standard_Real uprev = 0.0, vprev = 0.0, prm = 0.0, dist = 0.0;
33   Handle(TheTopolTool) Iter;
34
35   if (OnFirst) {
36     if(byinter) previousP.ParametersOnS1(uprev,vprev);
37     pt2d.SetCoord(sol(1),sol(2));
38     Iter = recdomain1;
39   }
40   else {
41     if(byinter) previousP.ParametersOnS2(uprev,vprev);
42     pt2d.SetCoord(sol(3),sol(4));
43     Iter = recdomain2;
44   }
45   lastpt2d.SetCoord(uprev,vprev);
46   Iter->Init();
47   while (Iter->More()) {
48     nbarc++; ok = 0;
49     if (OnFirst) {
50       if(byinter) { 
51         ok = okinter = TheBlendTool::Inters(pt2d,lastpt2d,
52                                             surf1,Iter->Value(),prm,dist); 
53       }
54       if(!ok) ok = TheBlendTool::Project(pt2d,surf1,Iter->Value(),prm,dist);
55     }
56     else {
57       if(byinter) { 
58         ok = okinter = TheBlendTool::Inters(pt2d,lastpt2d,
59                                             surf2,Iter->Value(),prm,dist); 
60       }
61       if(!ok) ok = TheBlendTool::Project(pt2d,surf2,Iter->Value(),prm,dist);
62     }
63     if (ok && (nbarc != PrevIndex) ) {
64       if (dist<distmin || okinter) {
65         distmin = dist;
66         ponarc = prm;
67         IndexSol = nbarc;
68         if(okinter && (PrevIndex==0)) break;
69       }
70     }
71     Iter->Next();
72   }
73   return IndexSol;
74 }
75
76 Standard_Boolean Blend_Walking::Recadre(Blend_FuncInv& FuncInv,
77                                         const Standard_Boolean OnFirst,
78                                         const math_Vector& sol,
79                                         math_Vector& solrst,
80                                         Standard_Integer& Indexsol,
81                                         Standard_Boolean& IsVtx,
82                                         TheVertex& Vtx,
83                                         const Standard_Real Extrap)
84
85 {
86   Standard_Boolean jalons_Trouve = Standard_False;
87   Standard_Boolean recadre = Standard_True, ok;
88   Standard_Boolean byinter = (line->NbPoints() != 0);
89 #ifndef DEB
90   Standard_Integer LeJalon = 0;
91 #else
92   Standard_Integer LeJalon;
93 #endif
94   Standard_Integer nbarc;
95   Standard_Real dist,prm,pmin, vtol;
96   gp_Pnt2d pt2d, lastpt2d;
97
98   math_Vector toler(1,4),infb(1,4),supb(1,4),valsol(1,4);
99
100   Handle(Adaptor2d_HCurve2d) thecur;
101   Handle(TheTopolTool) Iter;
102
103   if (OnFirst) Iter = recdomain1;
104   else         Iter = recdomain2;
105
106   Indexsol = ArcToRecadre(OnFirst, sol, 0, 
107                           lastpt2d, pt2d, pmin);
108   IsVtx = Standard_False;
109   if (Indexsol == 0) {
110     return Standard_False;
111   }
112
113   Iter->Init();
114   nbarc = 1;
115   while (nbarc < Indexsol) {
116     nbarc++;
117     Iter->Next();
118   }
119
120   TheArc thearc = Iter->Value();
121
122   if (OnFirst) {
123     thecur = TheBlendTool::CurveOnSurf(thearc,surf1);
124   }
125   else {
126     thecur = TheBlendTool::CurveOnSurf(thearc,surf2);
127   }
128
129 // Le probleme a resoudre
130   FuncInv.Set(OnFirst,thecur);
131   FuncInv.GetBounds(infb,supb);
132   infb(2) -= Extrap;
133   supb(2) += Extrap;
134   
135   FuncInv.GetTolerance(toler,tolesp/10);//Il vaut mieux garder un peu de marge
136   math_FunctionSetRoot rsnld(FuncInv,toler,35);
137   toler *= 10; // Mais on fait les tests correctements
138
139 // Calcul d'un point d'init
140   Standard_Real ufirst,ulast;
141   TheBlendTool::Bounds(thecur, ufirst,ulast);
142   // Pour aider a trouver les coins singuliers on recadre eventuelement le paramtere
143   if (Abs(pmin-ufirst) < Abs(ulast-ufirst)/1000) {
144     pmin = ufirst;
145   }
146   if (Abs(pmin-ulast) < Abs(ulast-ufirst)/1000) {
147     pmin = ulast;
148   }
149
150   if (byinter) { 
151     Standard_Real lastParam = previousP.Parameter();
152     // Verifie que le recadrage n'est pas un jalons
153     if (jalons.Length()!=0) {
154       Standard_Real t1, t2, t;
155       Standard_Boolean Cherche=Standard_True;
156       Standard_Integer ii;
157       if (lastParam < param) {
158         t1 = lastParam; t2 = param;
159       }
160       else {
161         t1 = param; t2 = lastParam;
162       }
163       for (ii=1; ii<=jalons.Length() && Cherche; ii++) {
164         t = jalons.Value(ii).Parameter();
165         if  (((t1 < t) && (t2 > t)) || (t==param)) {
166          jalons_Trouve = Standard_True;
167          LeJalon = ii;
168          Cherche = Standard_False; //Ne marche que si l'on sort simultanement
169        }
170         else Cherche = t < t2; // On s'arrete si t>=t2;
171       }
172     }
173     if (!jalons_Trouve) {
174       //Initialisation par Interpolation
175       Standard_Real lambda, u, v;
176       gp_Pnt2d Pnt, Pnt1, Pnt2;//,  POnC;
177       thecur->D0(pmin, Pnt);    
178       if (OnFirst) {
179         previousP.ParametersOnS2(u,v);
180         Pnt1.SetCoord(u, v);
181         Pnt2.SetCoord(sol(3), sol(4));
182       }
183       else {
184         previousP.ParametersOnS1(u,v);
185         Pnt1.SetCoord(u, v);
186         Pnt2.SetCoord(sol(1), sol(2));
187       }
188
189       lambda = Pnt.Distance(lastpt2d);
190       if (lambda > 1.e-12) lambda /=  Pnt.Distance(lastpt2d) + Pnt.Distance(pt2d);
191       else lambda = 0;
192       solrst(1) = pmin;
193       solrst(2) = (1-lambda)*lastParam + lambda*param;
194       solrst(3) = (1-lambda)*Pnt1.X()  + lambda*Pnt2.X();
195       solrst(4) = (1-lambda)*Pnt1.Y()  + lambda*Pnt2.Y();
196     }
197   }
198   else { // sinon on initialise par le dernier point calcule
199     solrst(1) = pmin;
200     solrst(2) = param; 
201     if (OnFirst) {
202       solrst(3) = sol(3);
203       solrst(4) = sol(4);
204     }
205     else {
206       solrst(3) = sol(1);
207       solrst(4) = sol(2);
208     }
209   }
210
211   if (jalons_Trouve) { // On recupere le jalon
212     Blend_Point MonJalon;
213     Standard_Boolean periodic;
214     Standard_Real uperiod = 0, vperiod = 0;
215     gp_Pnt2d Pnt;
216     Standard_Real distaux;
217     MonJalon = jalons.Value(LeJalon);
218     solrst(2) =  MonJalon.Parameter();
219     if (OnFirst) {
220       MonJalon.ParametersOnS2(solrst(3), solrst(4));
221       periodic = (surf2->IsUPeriodic() || surf2->IsVPeriodic());
222     }
223     else  {
224        MonJalon.ParametersOnS1(solrst(3), solrst(4));
225        periodic = (surf1->IsUPeriodic() || surf1->IsVPeriodic());
226      }
227
228     // Recadrage eventuelle pour le cas periodique
229     if (periodic) {
230       Handle(Adaptor3d_HSurface) surf;
231       if (OnFirst) surf = surf2;
232       else surf = surf1;
233
234       lastpt2d = thecur->Value(pmin);      
235
236       if (surf->IsUPeriodic()) {
237         uperiod =  surf->UPeriod();
238         if (solrst(3)-lastpt2d.X() >  uperiod*0.6) solrst(3) -= uperiod;
239         if (solrst(3)-lastpt2d.X() < -uperiod*0.6) solrst(3) += uperiod;
240       }
241       if (surf->IsVPeriodic()) {
242         vperiod =  surf->VPeriod();
243         if (solrst(4)-lastpt2d.Y() >  vperiod*0.6) solrst(4) -= vperiod;
244         if (solrst(4)-lastpt2d.Y() < -vperiod*0.6) solrst(4) += vperiod;
245       } 
246     }
247
248     // Pour le parametre sur arc il faut projeter...
249     pt2d.SetCoord(solrst(3), solrst(4));
250     Pnt = thecur->Value(ufirst);
251     dist = pt2d.Distance(Pnt);
252     solrst(1) = ufirst;
253     Pnt = thecur->Value(ulast);
254     distaux = pt2d.Distance(Pnt);
255     if ( distaux < dist) {
256       solrst(1) = ulast;
257       dist = distaux;
258     }
259
260     if (dist>Precision::PConfusion()) {
261       prm = pmin;
262       if (OnFirst) { 
263         ok = TheBlendTool::Project(pt2d,surf1,thearc,prm,distaux);
264       }
265       else {
266         ok = TheBlendTool::Project(pt2d,surf2,thearc,prm,distaux);
267       }
268       if (ok && (pt2d.Distance(thecur->Value(prm)) < dist)) solrst(1) = prm;
269       else solrst(1) = pmin;
270     }
271     // On verifie le jalon
272     jalons_Trouve = (FuncInv.IsSolution(solrst,tolesp));
273   }
274
275   if (!jalons_Trouve) {
276     // Resolution...
277     rsnld.Perform(FuncInv,solrst,infb,supb);  
278     if (!rsnld.IsDone()) {
279       cout << "Walking::Recadre : RSNLD not done " << endl;
280       recadre = Standard_False;
281     }
282     else {
283       rsnld.Root(solrst);
284       recadre = FuncInv.IsSolution(solrst,tolesp);
285     }
286   }
287
288   // En cas d'echecs, on regarde si un autre arc 
289   // peut faire l'affaire (cas des sorties a proximite d'un vertex)
290   dist = (ulast - ufirst)/100;
291   if ((!recadre) && 
292       ((Abs(pmin-ulast) < dist) || (Abs(pmin-ufirst) < dist)) ) {
293
294     Indexsol =  ArcToRecadre(OnFirst, sol, Indexsol, 
295                              lastpt2d, pt2d, pmin);
296     if (Indexsol == 0) {
297       return Standard_False;
298     }
299
300     Iter->Init();
301     nbarc = 1;
302     while (nbarc < Indexsol) {
303       nbarc++;
304       Iter->Next();
305     }
306     thearc = Iter->Value();
307  
308     if (OnFirst) {
309       thecur = TheBlendTool::CurveOnSurf(thearc,surf1);
310     }
311     else {
312       thecur = TheBlendTool::CurveOnSurf(thearc,surf2);
313     }
314     solrst(1) = pmin;
315     // Le probleme a resoudre
316     FuncInv.Set(OnFirst,thecur);
317     FuncInv.GetBounds(infb,supb);
318     FuncInv.GetTolerance(toler,tolesp/10);//Il vaut mieux garder un peu de marge
319     math_FunctionSetRoot rsnld(FuncInv,toler,35);
320     toler *= 10; // Mais on fait les tests correctements
321     // Resolution...
322     rsnld.Perform(FuncInv,solrst,infb,supb);
323   
324     if (!rsnld.IsDone()) {
325       cout << "Walking::Recadre : RSNLD not done " << endl;
326       recadre = Standard_False;
327     }
328     else {
329       rsnld.Root(solrst);
330       recadre = FuncInv.IsSolution(solrst,tolesp);
331     }
332   }
333
334   if (recadre) {
335     // Classification topologique  
336     if (OnFirst) {
337       thecur = TheBlendTool::CurveOnSurf(thearc,surf1);
338     }
339     else {
340       thecur = TheBlendTool::CurveOnSurf(thearc,surf2);
341     }
342     TheBlendTool::Bounds(thecur, ufirst,ulast);    
343
344     Iter->Initialize(thearc);
345     Iter->InitVertexIterator();
346     IsVtx = !Iter->MoreVertex();
347     while (!IsVtx) {
348       Vtx = Iter->Vertex();
349       vtol = 0.4*Abs(ulast-ufirst); // Un majorant de la tolerance
350       if (vtol > Max(TheBlendTool::Tolerance(Vtx,thearc), toler(1)))
351         vtol = Max(TheBlendTool::Tolerance(Vtx,thearc), toler(1));
352       if (Abs(TheBlendTool::Parameter(Vtx,thearc)-solrst(1)) <= vtol) {
353         IsVtx = Standard_True; // On est dans la boule du vertex ou 
354                                // le vertex est dans la "boule" du recadrage
355       }
356       else {
357         Iter->NextVertex();
358         IsVtx = !Iter->MoreVertex();
359       }
360     }
361     if (!Iter->MoreVertex()) {
362       IsVtx = Standard_False;
363     }
364     return Standard_True;
365   }
366   return Standard_False;
367 }
368
369
370 void Blend_Walking::Transition(const Standard_Boolean OnFirst,
371                                const TheArc& A,
372                                const Standard_Real Param,
373                                IntSurf_Transition& TLine,
374                                IntSurf_Transition& TArc)
375 {
376   Standard_Boolean computetranstionaveclacorde = 0;
377   gp_Vec tgline;
378   Blend_Point prevprev;
379
380   if(previousP.IsTangencyPoint()){
381     if(line->NbPoints() < 2) return;
382     computetranstionaveclacorde = 1;
383     if(sens < 0){
384       prevprev = line->Point(2);
385     }
386     else {
387       prevprev = line->Point(line->NbPoints() - 1);
388     }
389   }
390   gp_Pnt2d p2d;
391   gp_Vec2d dp2d;
392
393   gp_Pnt pbid;
394   gp_Vec d1u,d1v,normale,tgrst;
395   gp_Dir thenormal;
396   CSLib_NormalStatus stat;
397
398   TheArcTool::D1(A,Param,p2d,dp2d);
399   if (OnFirst) {
400     TheSurfaceTool::D1(surf1,p2d.X(),p2d.Y(),pbid,d1u,d1v);
401     if(!computetranstionaveclacorde) tgline = previousP.TangentOnS1();
402     else tgline = gp_Vec(prevprev.PointOnS1(),previousP.PointOnS1());
403   }
404   else {
405     TheSurfaceTool::D1(surf2,p2d.X(),p2d.Y(),pbid,d1u,d1v);
406     if(!computetranstionaveclacorde) tgline = previousP.TangentOnS2();
407     else tgline = gp_Vec(prevprev.PointOnS2(),previousP.PointOnS2());
408   }
409
410   tgrst.SetLinearForm(dp2d.X(),d1u,dp2d.Y(),d1v);
411
412   CSLib::Normal(d1u, d1v, 1.e-9, stat, thenormal);
413   if (stat ==  CSLib_Defined) normale.SetXYZ(thenormal.XYZ());
414   else {
415     Handle(Adaptor3d_HSurface) surf;
416     if (OnFirst) surf = surf1;
417     else         surf = surf2;
418     Standard_Integer iu, iv;
419     TColgp_Array2OfVec Der(0, 2 , 0, 2);
420     TheSurfaceTool::D2(surf,p2d.X(),p2d.Y(),pbid, Der(1,0), Der(0,1), 
421                        Der(2,0), Der(0,2), Der(1,1));
422     Der(2,1) = TheSurfaceTool::DN(surf, p2d.X(), p2d.Y(), 2,1);
423     Der(1,2) = TheSurfaceTool::DN(surf,p2d.X(),p2d.Y(), 1,2);
424     Der(2,2) = TheSurfaceTool::DN(surf,p2d.X(),p2d.Y(), 2,2);
425     CSLib::Normal(2, Der, 1.e-9,  
426                   p2d.X(), p2d.Y(), 
427                   TheSurfaceTool::FirstUParameter(surf),
428                   TheSurfaceTool::LastUParameter(surf),
429                   TheSurfaceTool::FirstVParameter(surf),
430                   TheSurfaceTool::LastVParameter(surf),
431                   stat, thenormal, iu, iv);
432     normale.SetXYZ(thenormal.XYZ());
433 #if DEB
434     if (stat == CSLib_InfinityOfSolutions)
435       cout << "Blend_Walking::Transition : Infinite de Normal" << endl;
436 #endif 
437   }
438
439   IntSurf::MakeTransition(tgline,tgrst,normale,TLine,TArc);
440
441 }
442
443
444 void Blend_Walking::MakeExtremity(TheExtremity& Extrem,
445                                   const Standard_Boolean OnFirst,
446                                   const Standard_Integer Index,
447                                   const Standard_Real Param,
448                                   const Standard_Boolean IsVtx,
449                                   const TheVertex& Vtx)
450 {
451
452   IntSurf_Transition Tline,Tarc;
453   Standard_Integer nbarc;
454   Handle(TheTopolTool) Iter;
455
456   if (OnFirst) {
457     Extrem.SetValue(previousP.PointOnS1(),
458                     sol(1),sol(2),
459                     previousP.Parameter(), tolesp);
460     if (!previousP.IsTangencyPoint())  
461       Extrem.SetTangent(previousP.TangentOnS1());
462     Iter = recdomain1;
463   }
464   else {
465     Extrem.SetValue(previousP.PointOnS2(),
466                     sol(3),sol(4),
467                     previousP.Parameter(), tolesp);
468     if (!previousP.IsTangencyPoint())  
469       Extrem.SetTangent(previousP.TangentOnS2());
470     Iter = recdomain2;
471   }
472
473   Iter->Init();
474   nbarc = 1;
475
476   while (nbarc < Index) {
477     nbarc++;
478     Iter->Next();
479   }
480
481   Transition(OnFirst,Iter->Value(),Param,Tline,Tarc);
482   Extrem.AddArc(Iter->Value(),Param,Tline,Tarc);
483   if (IsVtx) Extrem.SetVertex(Vtx);
484 }
485
486 void  Blend_Walking::MakeSingularExtremity( TheExtremity& Extrem,
487                                            const Standard_Boolean OnFirst,
488                                            const TheVertex& Vtx)
489 {
490   IntSurf_Transition Tline,Tarc;
491   Handle(TheTopolTool) Iter;
492   Standard_Real prm;
493
494   if (OnFirst) {
495     Iter = recdomain1;
496     if (!previousP.IsTangencyPoint())
497       Extrem.SetTangent(previousP.TangentOnS1());
498   }
499   else {
500     if (!previousP.IsTangencyPoint()) 
501       Extrem.SetTangent(previousP.TangentOnS2());
502     Iter = recdomain2;
503   }
504   
505   Iter->Init(); 
506   Extrem.SetVertex(Vtx);
507   while (Iter->More()) {
508     TheArc arc = Iter->Value();
509     Iter->Initialize(arc);
510     Iter->InitVertexIterator();
511     while (Iter->MoreVertex()) {
512       if (Iter->Identical(Vtx,Iter->Vertex())) {
513         prm = TheBlendTool::Parameter(Vtx,arc);
514         Transition(OnFirst,arc,prm,Tline,Tarc);
515         Extrem.AddArc(arc,prm,Tline,Tarc);
516       }
517       Iter->NextVertex();
518     }
519     Iter->Next();
520   }   
521 }
522
523
524
525
526
527
528
529
530
531
532