b311480e |
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 | |
7fd59977 |
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; |
1d47d8d0 |
94 | Standard_Integer Index1 = 0, Index2 = 0, nbarc; |
7fd59977 |
95 | Standard_Boolean Arrive,recad1,recad2, control; |
1d47d8d0 |
96 | Standard_Boolean Isvtx1 = Standard_False, Isvtx2 = Standard_False, echecrecad; |
7fd59977 |
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 | } |