b311480e |
1 | // Copyright (c) 1995-1999 Matra Datavision |
973c2be1 |
2 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
3 | // |
973c2be1 |
4 | // This file is part of Open CASCADE Technology software library. |
b311480e |
5 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
11 | // |
973c2be1 |
12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. |
b311480e |
14 | |
73d0a668 |
15 | #include <gce_MakePln.hxx> |
af99433e |
16 | #include <Extrema_ExtPS.hxx> |
17 | #include <Extrema_ExtPC.hxx> |
18 | |
1d54b807 |
19 | #ifdef DRAW |
20 | #include <DrawTrSurf.hxx> |
21 | #endif |
22 | |
23 | |
d66bd706 |
24 | static const Standard_Real CosRef3D = 0.88; |
25 | |
af99433e |
26 | static void RecadreIfPeriodic(Standard_Real& NewU, |
27 | Standard_Real& NewV, |
28 | const Standard_Real OldU, |
29 | const Standard_Real OldV, |
30 | const Standard_Real UPeriod, |
31 | const Standard_Real VPeriod) |
32 | { |
33 | if (UPeriod > 0.) |
34 | { |
35 | Standard_Real sign = (NewU < OldU)? 1 : -1; |
36 | while (Abs(NewU - OldU) > UPeriod/2) |
37 | NewU += sign * UPeriod; |
38 | } |
39 | if (VPeriod > 0.) |
40 | { |
41 | Standard_Real sign = (NewV < OldV)? 1 : -1; |
42 | while (Abs(NewV - OldV) > VPeriod/2) |
43 | NewV += sign * VPeriod; |
44 | } |
45 | } |
73d0a668 |
46 | |
7fd59977 |
47 | static void evalpinit(math_Vector& parinit, |
48 | const Blend_Point& previousP, |
49 | const Standard_Real parprec, |
50 | const Standard_Real param, |
51 | const math_Vector& infbound, |
52 | const math_Vector& supbound, |
53 | const Standard_Boolean classonS1, |
54 | const Standard_Boolean classonS2) |
55 | { |
56 | if(previousP.IsTangencyPoint()){ |
57 | previousP.ParametersOnS1(parinit(1),parinit(2)); |
58 | previousP.ParametersOnS2(parinit(3),parinit(4)); |
59 | } |
60 | else { |
61 | Standard_Real u1,v1,u2,v2; |
62 | Standard_Real du1,dv1,du2,dv2; |
63 | Standard_Boolean Inside=Standard_True; |
64 | previousP.ParametersOnS1(u1,v1); |
65 | previousP.ParametersOnS2(u2,v2); |
66 | previousP.Tangent2dOnS1().Coord(du1,dv1); |
67 | previousP.Tangent2dOnS2().Coord(du2,dv2); |
68 | Standard_Real step = param - parprec; |
69 | u1+= step*du1; |
70 | v1+= step*dv1; |
71 | if ( classonS1 ) { |
72 | if ((u1<infbound(1)) || (u1>supbound(1))) Inside=Standard_False; |
73 | if ((v1<infbound(2)) || (v1>supbound(2))) Inside=Standard_False; |
74 | } |
75 | u2+= step*du2; |
76 | v2+= step*dv2; |
77 | if ( classonS2) { |
78 | if ((u2<infbound(3)) || (u2>supbound(3))) Inside=Standard_False; |
79 | if ((v2<infbound(4)) || (v2>supbound(4))) Inside=Standard_False; |
80 | } |
81 | |
82 | if (Inside) { |
83 | parinit(1) = u1; |
84 | parinit(2) = v1; |
85 | parinit(3) = u2; |
86 | parinit(4) = v2; |
87 | } |
88 | else { // on ne joue pas au plus malin |
89 | previousP.ParametersOnS1(parinit(1),parinit(2)); |
90 | previousP.ParametersOnS2(parinit(3),parinit(4)); |
91 | } |
92 | |
93 | } |
94 | } |
95 | |
96 | |
97 | |
98 | void Blend_Walking::InternalPerform(Blend_Function& Func, |
99 | Blend_FuncInv& FuncInv, |
100 | const Standard_Real Bound) |
101 | { |
d66bd706 |
102 | Standard_Real Cosi = 0., Cosi2 = 0.; |
7fd59977 |
103 | |
104 | Standard_Real stepw = pasmax; |
105 | Standard_Integer nbp = line->NbPoints(); |
106 | if(nbp >= 2){ //On reprend le dernier step s'il n est pas trop petit. |
107 | if(sens < 0.){ |
108 | stepw = (line->Point(2).Parameter() - line->Point(1).Parameter()); |
109 | } |
110 | else{ |
111 | stepw = (line->Point(nbp).Parameter() - line->Point(nbp - 1).Parameter()); |
112 | } |
113 | stepw = Max(stepw,100.*tolgui); |
114 | } |
115 | Standard_Real parprec = param; |
d66bd706 |
116 | gp_Vec TgOnGuide, PrevTgOnGuide; |
117 | gp_Pnt PtOnGuide; |
118 | hguide->D1(parprec, PtOnGuide, TgOnGuide); |
119 | PrevTgOnGuide = TgOnGuide; |
7fd59977 |
120 | |
121 | if (sens*(parprec - Bound) >= -tolgui) { |
122 | return; |
123 | } |
124 | Blend_Status State = Blend_OnRst12; |
125 | TopAbs_State situ1 =TopAbs_IN,situ2=TopAbs_IN; |
126 | Standard_Real w1,w2; |
1d47d8d0 |
127 | Standard_Integer Index1 = 0, Index2 = 0, nbarc; |
7fd59977 |
128 | Standard_Boolean Arrive,recad1,recad2, control; |
1d47d8d0 |
129 | Standard_Boolean Isvtx1 = Standard_False, Isvtx2 = Standard_False, echecrecad; |
7fd59977 |
130 | gp_Pnt2d p2d; |
131 | math_Vector tolerance(1,4),infbound(1,4),supbound(1,4),parinit(1,4); |
132 | math_Vector solrst1(1,4),solrst2(1,4); |
133 | TheVertex Vtx1,Vtx2; |
134 | TheExtremity Ext1,Ext2; |
135 | |
136 | //IntSurf_Transition Tline,Tarc; |
137 | |
138 | Func.GetTolerance(tolerance,tolesp); |
139 | Func.GetBounds(infbound,supbound); |
140 | |
141 | math_FunctionSetRoot rsnld(Func,tolerance,30); |
142 | parinit = sol; |
143 | |
144 | Arrive = Standard_False; |
145 | param = parprec + sens*stepw; |
146 | if(sens *(param - Bound) > 0.) { |
147 | stepw = sens*(Bound - parprec)*0.5; |
148 | param = parprec + sens*stepw; |
149 | } |
150 | |
151 | evalpinit(parinit,previousP,parprec,param, |
152 | infbound,supbound, clasonS1, clasonS2); |
153 | |
154 | while (!Arrive) { |
155 | |
0797d9d3 |
156 | #ifdef OCCT_DEBUG |
7fd59977 |
157 | sectioncalculee = 0; |
158 | nbcomputedsection++; |
159 | #endif |
d66bd706 |
160 | |
161 | hguide->D1(param, PtOnGuide, TgOnGuide); |
162 | //Check deflection on guide |
163 | Cosi = PrevTgOnGuide * TgOnGuide; |
164 | if (Cosi < gp::Resolution()) //angle>=pi/2 or null magnitude |
165 | Cosi2 = 0.; |
166 | else |
167 | Cosi2 = Cosi * Cosi / PrevTgOnGuide.SquareMagnitude() / TgOnGuide.SquareMagnitude(); |
168 | if (Cosi2 < CosRef3D) //angle 3d too great |
169 | { |
170 | State = Blend_StepTooLarge; |
171 | stepw = stepw/2.; |
172 | param = parprec + sens*stepw; // on ne risque pas de depasser Bound. |
173 | if (Abs(stepw) < tolgui) { |
174 | Ext1.SetValue(previousP.PointOnS1(), |
175 | sol(1),sol(2), |
176 | previousP.Parameter(),tolesp); |
177 | Ext2.SetValue(previousP.PointOnS2(), |
178 | sol(3),sol(4), |
179 | previousP.Parameter(),tolesp); |
180 | if (!previousP.IsTangencyPoint()) { |
181 | Ext1.SetTangent(previousP.TangentOnS1()); |
182 | Ext2.SetTangent(previousP.TangentOnS2()); |
183 | } |
184 | Arrive = Standard_True; |
185 | } |
186 | continue; |
187 | } |
188 | PrevTgOnGuide = TgOnGuide; |
189 | ////////////////////////// |
190 | |
7fd59977 |
191 | Standard_Boolean bonpoint = 1; |
192 | Func.Set(param); |
193 | rsnld.Perform(Func,parinit,infbound,supbound); |
194 | |
195 | if (!rsnld.IsDone()) { |
196 | State = Blend_StepTooLarge; |
197 | bonpoint = 0; |
198 | } |
199 | else { |
200 | rsnld.Root(sol); |
201 | |
202 | if(clasonS1) situ1 = domain1->Classify(gp_Pnt2d(sol(1),sol(2)), |
203 | Min(tolerance(1),tolerance(2)),0); |
204 | else situ1 = TopAbs_IN; |
205 | if(clasonS2) situ2 = domain2->Classify(gp_Pnt2d(sol(3),sol(4)), |
206 | Min(tolerance(3),tolerance(4)),0); |
207 | else situ2 = TopAbs_IN; |
208 | } |
209 | if(bonpoint && line->NbPoints() == 1 && (situ1 != TopAbs_IN || situ2 != TopAbs_IN)){ |
210 | State = Blend_StepTooLarge; |
211 | bonpoint = 0; |
212 | } |
213 | if(bonpoint){ |
214 | w1 = w2 = Bound; |
215 | recad1 = Standard_False; |
216 | recad2 = Standard_False; |
217 | echecrecad = Standard_False; |
218 | control = Standard_False; |
219 | |
220 | if (situ1 == TopAbs_OUT || situ1 == TopAbs_ON) { |
221 | // pb inverse sur surf1 |
222 | //Si le recadrage s'effectue dans le sens de la progression a une tolerance pres, |
223 | //on a pris la mauvaise solution. |
224 | recad1 = Recadre(FuncInv,Standard_True, |
225 | sol,solrst1,Index1,Isvtx1,Vtx1); |
226 | |
227 | if (recad1) { |
228 | Standard_Real wtemp; |
229 | wtemp = solrst1(2); |
230 | if ((param - wtemp)/sens>= -10*tolesp){ |
231 | w1 = solrst1(2); |
232 | control = Standard_True; |
233 | } |
234 | else { |
235 | echecrecad = Standard_True; |
236 | recad1 = Standard_False; |
237 | State = Blend_StepTooLarge; |
238 | bonpoint = 0; |
239 | stepw = stepw/2.; |
240 | } |
241 | } |
242 | else { |
243 | echecrecad = Standard_True; |
244 | } |
245 | } |
246 | if (situ2 == TopAbs_OUT || situ2 == TopAbs_ON) { |
247 | // pb inverse sur surf2 |
248 | //Si le recadrage s'effectue dans le sens de la progression a une tolerance pres, |
249 | //on a pris la mauvaise solution. |
250 | recad2 = Recadre(FuncInv,Standard_False, |
251 | sol,solrst2,Index2,Isvtx2,Vtx2); |
252 | |
253 | if (recad2) { |
254 | Standard_Real wtemp; |
255 | wtemp = solrst2(2); |
256 | if ((param - wtemp)/sens>= -10*tolesp){ |
257 | w2 = solrst2(2); |
258 | control = Standard_True; |
259 | } |
260 | else { |
261 | echecrecad = Standard_True; |
262 | recad2 = Standard_False; |
263 | State = Blend_StepTooLarge; |
264 | bonpoint = 0; |
265 | stepw = stepw/2.; |
266 | } |
267 | } |
268 | else { |
269 | echecrecad = Standard_True; |
270 | } |
271 | } |
272 | |
273 | // Que faut il controler |
274 | if (recad1 && recad2) { |
275 | if (Abs(w1-w2) <= 10*tolgui) { |
276 | // pas besoin de controler les recadrage |
277 | // Le control pouvant se planter (cf model blend10) |
278 | // La tolerance est choisie grossse afin, de permetre au |
279 | // cheminement suivant, de poser quelques sections ... |
280 | control = Standard_False; |
281 | } |
282 | else if (sens*(w1-w2) < 0.) { |
283 | //sol sur 1 ? |
284 | recad2 = Standard_False; |
285 | } |
286 | else { |
287 | //sol sur 2 ? |
288 | recad1 = Standard_False; |
289 | } |
290 | } |
291 | |
292 | // Controle effectif des recadrage |
293 | if (control) { |
294 | TopAbs_State situ; |
295 | if (recad1 && clasonS2) { |
296 | situ = recdomain2->Classify(gp_Pnt2d(solrst1(3),solrst1(4)), |
297 | Min(tolerance(3),tolerance(4))); |
298 | if (situ == TopAbs_OUT) { |
299 | recad1 = Standard_False; |
300 | echecrecad = Standard_True; |
301 | } |
302 | } |
303 | else if (recad2 && clasonS1) { |
304 | situ = recdomain1->Classify(gp_Pnt2d(solrst2(3),solrst2(4)), |
305 | Min(tolerance(1),tolerance(1))); |
306 | if (situ == TopAbs_OUT) { |
307 | recad2 = Standard_False; |
308 | echecrecad = Standard_True; |
309 | } |
310 | } |
311 | } |
312 | |
313 | if(recad1 || recad2) echecrecad = Standard_False; |
314 | |
315 | if (!echecrecad) { |
316 | if (recad1 && recad2) { |
317 | //sol sur 1 et 2 a la fois |
318 | // On passe par les arcs , pour ne pas avoir de probleme |
319 | // avec les surfaces periodiques. |
320 | State = Blend_OnRst12; |
321 | param = (w1+w2)/2; |
73d0a668 |
322 | gp_Pnt Pnt1, Pnt2; |
7fd59977 |
323 | p2d = TheArcTool::Value(recdomain1->Value(),solrst1(1)); |
324 | sol(1) = p2d.X(); |
325 | sol(2) = p2d.Y(); |
73d0a668 |
326 | Pnt1 = TheSurfaceTool::Value(surf1,sol(1),sol(2)); |
7fd59977 |
327 | p2d = TheArcTool::Value(recdomain2->Value(),solrst2(1)); |
328 | sol(3) = p2d.X(); |
329 | sol(4) = p2d.Y(); |
73d0a668 |
330 | Pnt2 = TheSurfaceTool::Value(surf2,sol(3),sol(4)); |
af99433e |
331 | const Standard_Real TolProd = 1.e-5; |
332 | Standard_Real SavedParams [2]; |
333 | Standard_Boolean SameDirs [2] = {Standard_False, Standard_False}; |
c22b52d6 |
334 | ChFiDS_ElSpine& theElSpine = *hguide; |
af99433e |
335 | SavedParams[0] = theElSpine.GetSavedFirstParameter(); |
336 | SavedParams[1] = theElSpine.GetSavedLastParameter(); |
337 | for (Standard_Integer ind = 0; ind < 2; ind++) |
73d0a668 |
338 | { |
af99433e |
339 | if (!Precision::IsInfinite(SavedParams[ind])) |
73d0a668 |
340 | { |
af99433e |
341 | //Check the original first and last parameters of guide curve |
342 | //for equality to found parameter <param>: |
343 | //check equality of tangent to guide curve and |
344 | //normal to plane built on 3 points: |
345 | //point on guide curve and points on restrictions of adjacent |
346 | //surfaces. |
347 | gp_Pnt Pnt0; |
348 | gp_Vec Dir0; |
349 | hguide->D1(SavedParams[ind], Pnt0, Dir0); |
350 | Standard_Real Length = Dir0.Magnitude(); |
351 | if (Length <= gp::Resolution()) |
352 | continue; |
353 | Dir0 /= Length; |
354 | gce_MakePln PlaneBuilder(Pnt0, Pnt1, Pnt2); |
355 | if (!PlaneBuilder.IsDone()) |
356 | continue; |
357 | gp_Pln thePlane = PlaneBuilder.Value(); |
358 | gp_Dir DirPlane = thePlane.Axis().Direction(); |
359 | gp_Vec theProd = Dir0 ^ DirPlane; |
360 | Standard_Real ProdMod = theProd.Magnitude(); |
361 | if (ProdMod <= TolProd) |
362 | SameDirs[ind] = Standard_True; |
73d0a668 |
363 | } |
73d0a668 |
364 | } |
af99433e |
365 | Standard_Real theParam = Precision::Infinite(); |
366 | //Choose the closest parameter |
367 | if (SameDirs[0] && SameDirs[1]) |
368 | theParam = (Abs(param - SavedParams[0]) < Abs(param - SavedParams[1]))? |
369 | SavedParams[0] : SavedParams[1]; |
370 | else if (SameDirs[0]) |
371 | theParam = SavedParams[0]; |
372 | else if (SameDirs[1]) |
373 | theParam = SavedParams[1]; |
374 | |
375 | Standard_Real NewU, NewV, NewParam; |
376 | gp_Pnt NewPnt; |
377 | Standard_Boolean Corrected = CorrectExtremityOnOneRst(1, sol(3), sol(4), param, Pnt1, |
378 | NewU, NewV, NewPnt, NewParam); |
379 | if (Corrected) |
380 | { |
381 | if (Abs(param - NewParam) < Abs(param - theParam)) |
382 | theParam = NewParam; |
383 | } |
384 | |
385 | if (!Precision::IsInfinite(theParam)) |
386 | param = theParam; |
7fd59977 |
387 | } |
388 | else if (recad1) { |
389 | // sol sur 1 |
390 | State = Blend_OnRst1; |
391 | param = w1; |
392 | recdomain1->Init(); |
393 | nbarc = 1; |
394 | while (nbarc < Index1) { |
395 | nbarc++; |
396 | recdomain1->Next(); |
397 | } |
398 | p2d = TheArcTool::Value(recdomain1->Value(),solrst1(1)); |
399 | sol(1) = p2d.X(); |
400 | sol(2) = p2d.Y(); |
401 | sol(3) = solrst1(3); |
402 | sol(4) = solrst1(4); |
af99433e |
403 | gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf1,sol(1),sol(2)); |
404 | Standard_Real NewU, NewV, NewParam; |
405 | gp_Pnt NewPnt; |
406 | Standard_Boolean Corrected = CorrectExtremityOnOneRst(1, sol(3), sol(4), param, thePntOnRst, |
407 | NewU, NewV, NewPnt, NewParam); |
408 | if (Corrected) |
409 | { |
410 | param = NewParam; |
411 | sol(3) = NewU; |
412 | sol(4) = NewV; |
413 | } |
7fd59977 |
414 | } |
415 | else if (recad2) { |
416 | //sol sur 2 |
417 | State = Blend_OnRst2; |
418 | param = w2; |
419 | |
420 | recdomain2->Init(); |
421 | nbarc = 1; |
422 | while (nbarc < Index2) { |
423 | nbarc++; |
424 | recdomain2->Next(); |
425 | } |
426 | p2d = TheArcTool::Value(recdomain2->Value(),solrst2(1)); |
427 | sol(1) = solrst2(3); |
428 | sol(2) = solrst2(4); |
429 | sol(3) = p2d.X(); |
430 | sol(4) = p2d.Y(); |
af99433e |
431 | gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf2,sol(3),sol(4)); |
432 | Standard_Real NewU, NewV, NewParam; |
433 | gp_Pnt NewPnt; |
434 | Standard_Boolean Corrected = CorrectExtremityOnOneRst(2, sol(1), sol(2), param, thePntOnRst, |
435 | NewU, NewV, NewPnt, NewParam); |
436 | if (Corrected) |
437 | { |
438 | param = NewParam; |
439 | sol(1) = NewU; |
440 | sol(2) = NewV; |
441 | } |
7fd59977 |
442 | } |
443 | else { |
444 | State = Blend_OK; |
445 | } |
446 | |
447 | Standard_Boolean testdefl = 1; |
0797d9d3 |
448 | #ifdef OCCT_DEBUG |
7fd59977 |
449 | testdefl = !Blend_GetcontextNOTESTDEFL(); |
450 | #endif |
451 | if (recad1 || recad2) { |
452 | Func.Set(param); |
453 | // Il vaut mieux un pas non orthodoxe que pas de recadrage!! PMN |
454 | State = TestArret(Func, State, |
455 | (testdefl && (Abs(stepw) > 3*tolgui)), |
456 | Standard_False, Standard_True); |
457 | } |
458 | else { |
459 | State = TestArret(Func, State, testdefl); |
460 | } |
461 | } |
462 | else { |
463 | // Ou bien le pas max est mal regle. On divise. |
464 | // if(line->NbPoints() == 1) State = Blend_StepTooLarge; |
465 | if (stepw > 2*tolgui) State = Blend_StepTooLarge; |
466 | // Sinon echec recadrage. On sort avec PointsConfondus |
467 | else { |
0797d9d3 |
468 | #ifdef OCCT_DEBUG |
04232180 |
469 | std::cout << "Echec recadrage" << std::endl; |
7fd59977 |
470 | #endif |
471 | State = Blend_SamePoints; |
472 | } |
473 | } |
474 | } |
475 | |
0797d9d3 |
476 | #ifdef OCCT_DEBUG |
7fd59977 |
477 | if (Blend_GettraceDRAWSECT()){ |
478 | Drawsect(surf1,surf2,sol,param,Func, State); |
479 | } |
480 | #endif |
481 | switch (State) { |
482 | case Blend_OK : |
483 | { |
484 | // Mettre a jour la ligne. |
485 | if (sens>0.) { |
486 | line->Append(previousP); |
487 | } |
488 | else { |
489 | line->Prepend(previousP); |
490 | } |
1d54b807 |
491 | #ifdef DRAW |
492 | Standard_Integer nbpts = line->NbPoints(); |
493 | char name [100]; |
494 | sprintf(name, "pg%d", nbpts); |
495 | DrawTrSurf::Set(name, PtOnGuide); |
496 | sprintf(name, "p1_%d", nbpts); |
497 | DrawTrSurf::Set(name, previousP.PointOnS1()); |
498 | sprintf(name, "p2_%d", nbpts); |
499 | DrawTrSurf::Set(name, previousP.PointOnS2()); |
500 | #endif |
7fd59977 |
501 | |
502 | parprec = param; |
503 | |
504 | if (param == Bound) { |
505 | Arrive = Standard_True; |
506 | Ext1.SetValue(previousP.PointOnS1(), |
507 | sol(1),sol(2), |
508 | previousP.Parameter(), tolesp); |
509 | Ext2.SetValue(previousP.PointOnS2(), |
510 | sol(3),sol(4), |
511 | previousP.Parameter(), tolesp); |
512 | if (!previousP.IsTangencyPoint()) { |
513 | Ext1.SetTangent(previousP.TangentOnS1()); |
514 | Ext2.SetTangent(previousP.TangentOnS2()); |
515 | } |
516 | |
517 | // Indiquer que fin sur Bound. |
518 | } |
519 | else { |
520 | param = param + sens*stepw; |
521 | if (sens*(param - Bound) > - tolgui) { |
522 | param = Bound; |
523 | } |
524 | } |
525 | evalpinit(parinit,previousP,parprec,param, |
526 | infbound,supbound, clasonS1, clasonS2); |
527 | } |
528 | break; |
529 | |
530 | case Blend_StepTooLarge : |
531 | { |
532 | stepw = stepw/2.; |
533 | if (Abs(stepw) < tolgui) { |
534 | Ext1.SetValue(previousP.PointOnS1(), |
535 | sol(1),sol(2), |
536 | previousP.Parameter(),tolesp); |
537 | Ext2.SetValue(previousP.PointOnS2(), |
538 | sol(3),sol(4), |
539 | previousP.Parameter(),tolesp); |
540 | if (!previousP.IsTangencyPoint()) { |
541 | Ext1.SetTangent(previousP.TangentOnS1()); |
542 | Ext2.SetTangent(previousP.TangentOnS2()); |
543 | } |
544 | Arrive = Standard_True; |
545 | if (line->NbPoints()>=2) { |
546 | // Indiquer qu on s arrete en cours de cheminement |
547 | } |
548 | // else { |
549 | // line->Clear(); |
550 | // } |
551 | } |
552 | else { |
553 | param = parprec + sens*stepw; // on ne risque pas de depasser Bound. |
554 | evalpinit(parinit,previousP,parprec,param, |
555 | infbound,supbound, clasonS1, clasonS2); |
556 | } |
557 | } |
558 | break; |
559 | |
560 | case Blend_StepTooSmall : |
561 | { |
562 | // Mettre a jour la ligne. |
563 | if (sens>0.) { |
564 | line->Append(previousP); |
565 | } |
566 | else { |
567 | line->Prepend(previousP); |
568 | } |
1d54b807 |
569 | #ifdef DRAW |
570 | Standard_Integer nbpts = line->NbPoints(); |
571 | char name [100]; |
572 | sprintf(name, "pg%d", nbpts); |
573 | DrawTrSurf::Set(name, PtOnGuide); |
574 | sprintf(name, "p1_%d", nbpts); |
575 | DrawTrSurf::Set(name, previousP.PointOnS1()); |
576 | sprintf(name, "p2_%d", nbpts); |
577 | DrawTrSurf::Set(name, previousP.PointOnS2()); |
578 | #endif |
7fd59977 |
579 | |
580 | parprec = param; |
581 | |
582 | stepw = Min(1.5*stepw,pasmax); |
583 | if (param == Bound) { |
584 | Arrive = Standard_True; |
585 | Ext1.SetValue(previousP.PointOnS1(), |
586 | sol(1),sol(2), |
587 | previousP.Parameter(),tolesp); |
588 | Ext2.SetValue(previousP.PointOnS2(), |
589 | sol(3),sol(4), |
590 | previousP.Parameter(),tolesp); |
591 | if (!previousP.IsTangencyPoint()) { |
592 | Ext1.SetTangent(previousP.TangentOnS1()); |
593 | Ext2.SetTangent(previousP.TangentOnS2()); |
594 | } |
595 | // Indiquer que fin sur Bound. |
596 | } |
597 | else { |
598 | param = param + sens*stepw; |
599 | if (sens*(param - Bound) > - tolgui) { |
600 | param = Bound; |
601 | } |
602 | } |
603 | evalpinit(parinit,previousP,parprec,param, |
604 | infbound,supbound, clasonS1, clasonS2); |
605 | } |
606 | break; |
607 | |
608 | case Blend_OnRst1 : |
609 | { |
610 | if (sens>0.) { |
611 | line->Append(previousP); |
612 | } |
613 | else { |
614 | line->Prepend(previousP); |
615 | } |
1d54b807 |
616 | #ifdef DRAW |
617 | Standard_Integer nbpts = line->NbPoints(); |
618 | char name [100]; |
619 | sprintf(name, "pg%d", nbpts); |
620 | DrawTrSurf::Set(name, PtOnGuide); |
621 | sprintf(name, "p1_%d", nbpts); |
622 | DrawTrSurf::Set(name, previousP.PointOnS1()); |
623 | sprintf(name, "p2_%d", nbpts); |
624 | DrawTrSurf::Set(name, previousP.PointOnS2()); |
625 | #endif |
626 | |
7fd59977 |
627 | MakeExtremity(Ext1,Standard_True,Index1, |
628 | solrst1(1),Isvtx1,Vtx1); |
629 | // On blinde le cas singulier ou un des recadrage a planter |
630 | if (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2*tolesp)) { |
631 | Ext2.SetValue(previousP.PointOnS1(), |
632 | sol(3),sol(4),tolesp); |
633 | if (Isvtx1) MakeSingularExtremity(Ext2, Standard_False, Vtx1); |
634 | } |
635 | else { |
636 | Ext2.SetValue(previousP.PointOnS2(), |
637 | sol(3),sol(4), |
638 | previousP.Parameter(),tolesp); |
639 | } |
640 | Arrive = Standard_True; |
641 | } |
642 | break; |
643 | |
644 | case Blend_OnRst2 : |
645 | { |
646 | if (sens>0.) { |
647 | line->Append(previousP); |
648 | } |
649 | else { |
650 | line->Prepend(previousP); |
651 | } |
1d54b807 |
652 | #ifdef DRAW |
653 | Standard_Integer nbpts = line->NbPoints(); |
654 | char name [100]; |
655 | sprintf(name, "pg%d", nbpts); |
656 | DrawTrSurf::Set(name, PtOnGuide); |
657 | sprintf(name, "p1_%d", nbpts); |
658 | DrawTrSurf::Set(name, previousP.PointOnS1()); |
659 | sprintf(name, "p2_%d", nbpts); |
660 | DrawTrSurf::Set(name, previousP.PointOnS2()); |
661 | #endif |
662 | |
7fd59977 |
663 | // On blinde le cas singulier ou un des recadrage a plante |
664 | if (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2*tolesp)) { |
665 | Ext1.SetValue(previousP.PointOnS2(), |
666 | sol(1),sol(2),tolesp); |
667 | if (Isvtx2) MakeSingularExtremity(Ext1, Standard_True, Vtx2); |
668 | } |
669 | else { |
670 | Ext1.SetValue(previousP.PointOnS1(), |
671 | sol(1),sol(2), |
672 | previousP.Parameter(),tolesp); |
673 | } |
674 | MakeExtremity(Ext2,Standard_False,Index2, |
675 | solrst2(1),Isvtx2,Vtx2); |
676 | Arrive = Standard_True; |
677 | } |
678 | break; |
679 | |
680 | |
681 | case Blend_OnRst12 : |
682 | { |
683 | if (sens>0.) { |
684 | line->Append(previousP); |
685 | } |
686 | else { |
687 | line->Prepend(previousP); |
688 | } |
1d54b807 |
689 | #ifdef DRAW |
690 | Standard_Integer nbpts = line->NbPoints(); |
691 | char name [100]; |
692 | sprintf(name, "pg%d", nbpts); |
693 | DrawTrSurf::Set(name, PtOnGuide); |
694 | sprintf(name, "p1_%d", nbpts); |
695 | DrawTrSurf::Set(name, previousP.PointOnS1()); |
696 | sprintf(name, "p2_%d", nbpts); |
697 | DrawTrSurf::Set(name, previousP.PointOnS2()); |
698 | #endif |
7fd59977 |
699 | |
700 | if ( (Isvtx1 != Isvtx2) && |
701 | (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2*tolesp)) ) { |
702 | // On blinde le cas singulier ou un seul recadrage |
703 | // est reconnu comme vertex. |
704 | if (Isvtx1) { |
705 | Isvtx2 = Standard_True; |
706 | Vtx2 = Vtx1; |
707 | } |
708 | else { |
709 | Isvtx1 = Standard_True; |
710 | Vtx1 = Vtx2; |
711 | } |
712 | } |
713 | |
714 | MakeExtremity(Ext1,Standard_True,Index1, |
715 | solrst1(1),Isvtx1,Vtx1); |
716 | MakeExtremity(Ext2,Standard_False,Index2, |
717 | solrst2(1),Isvtx2,Vtx2); |
718 | Arrive = Standard_True; |
719 | } |
720 | break; |
721 | |
722 | case Blend_SamePoints : |
723 | { |
724 | // On arrete |
0797d9d3 |
725 | #ifdef OCCT_DEBUG |
04232180 |
726 | std::cout << " Points confondus dans le cheminement" << std::endl; |
7fd59977 |
727 | #endif |
728 | Ext1.SetValue(previousP.PointOnS1(), |
729 | sol(1),sol(2), |
730 | previousP.Parameter(),tolesp); |
731 | Ext2.SetValue(previousP.PointOnS2(), |
732 | sol(3),sol(4), |
8c2d3314 |
733 | previousP.Parameter(),tolesp); |
7fd59977 |
734 | if (!previousP.IsTangencyPoint()) { |
735 | Ext1.SetTangent(previousP.TangentOnS1()); |
736 | Ext2.SetTangent(previousP.TangentOnS2()); |
737 | } |
738 | Arrive = Standard_True; |
739 | } |
740 | break; |
7fd59977 |
741 | default: |
742 | break; |
7fd59977 |
743 | } |
744 | if (Arrive) { |
745 | if (sens > 0.) { |
746 | line->SetEndPoints(Ext1,Ext2); |
747 | } |
748 | else { |
749 | line->SetStartPoints(Ext1,Ext2); |
750 | |
751 | } |
752 | } |
753 | |
754 | } |
755 | |
756 | } |
af99433e |
757 | |
758 | Standard_Boolean Blend_Walking::CorrectExtremityOnOneRst(const Standard_Integer IndexOfRst, |
759 | const Standard_Real theU, |
760 | const Standard_Real theV, |
761 | const Standard_Real theParam, |
762 | const gp_Pnt& thePntOnRst, |
763 | Standard_Real& NewU, |
764 | Standard_Real& NewV, |
765 | gp_Pnt& NewPoint, |
766 | Standard_Real& NewParam) const |
767 | { |
768 | const Standard_Real TolAng = 0.001; //bug OCC25701 |
769 | |
c22b52d6 |
770 | ChFiDS_ElSpine& theElSpine = *hguide; |
af99433e |
771 | if (theElSpine.NbVertices() == 0) |
772 | return Standard_False; |
773 | |
774 | Handle(TheTopolTool) DomainOfRst = (IndexOfRst == 1)? recdomain1 : recdomain2; |
775 | TheSurface SurfOfRst = (IndexOfRst == 1)? surf1 : surf2; |
776 | TheSurface AnotherSurf = (IndexOfRst == 1)? surf2 : surf1; |
777 | |
778 | //Correct point on surface 2 |
779 | //First we find right <param> |
780 | Standard_Real Ends [2]; |
781 | Ends[0] = TheArcTool::FirstParameter(DomainOfRst->Value()); |
782 | Ends[1] = TheArcTool::LastParameter(DomainOfRst->Value()); |
783 | Standard_Real GlobalMinSqDist = Precision::Infinite(); |
784 | Standard_Real ParamOnGuide = 0; |
785 | gp_Pnt PointOnGuide; |
786 | for (Standard_Integer k = 0; k < 2; k++) |
787 | { |
788 | gp_Pnt2d P2dOnEnd = TheArcTool::Value(DomainOfRst->Value(), Ends[k]); |
789 | gp_Pnt PntOnEnd = TheSurfaceTool::Value(SurfOfRst, P2dOnEnd.X(), P2dOnEnd.Y()); |
790 | Extrema_ExtPC projoncurv(PntOnEnd, theElSpine); |
791 | if (!projoncurv.IsDone()) |
792 | continue; |
793 | Standard_Real MinSqDist = Precision::Infinite(); |
794 | Standard_Integer imin = 0; |
795 | for (Standard_Integer ind = 1; ind <= projoncurv.NbExt(); ind++) |
796 | { |
797 | Standard_Real aSqDist = projoncurv.SquareDistance(ind); |
798 | if (aSqDist < MinSqDist) |
799 | { |
800 | MinSqDist = aSqDist; |
801 | imin = ind; |
802 | } |
803 | } |
804 | if (MinSqDist < GlobalMinSqDist) |
805 | { |
806 | GlobalMinSqDist = MinSqDist; |
807 | ParamOnGuide = projoncurv.Point(imin).Parameter(); |
808 | PointOnGuide = projoncurv.Point(imin).Value(); |
809 | } |
810 | } |
811 | NewParam = ParamOnGuide; |
812 | if (hguide->IsPeriodic()) |
813 | { |
814 | Standard_Real Period = hguide->Period(); |
815 | Standard_Real sign = (NewParam < theParam)? 1 : -1; |
816 | while (Abs(NewParam - theParam) > Period/2) |
817 | NewParam += sign *Period; |
818 | } |
819 | |
820 | //Second we find right point and tangent on guide |
821 | GlobalMinSqDist = Precision::Infinite(); |
822 | gp_Ax1 theAx1; |
823 | for (Standard_Integer ind = 1; ind <= theElSpine.NbVertices(); ind++) |
824 | { |
825 | const gp_Ax1& anAx1 = theElSpine.VertexWithTangent(ind); |
826 | gp_Pnt aPnt = anAx1.Location(); |
827 | Standard_Real aSqDist = PointOnGuide.SquareDistance(aPnt); |
828 | if (aSqDist < GlobalMinSqDist) |
829 | { |
830 | GlobalMinSqDist = aSqDist; |
831 | theAx1 = anAx1; |
832 | } |
833 | } |
834 | const gp_Pnt& Pnt0 = theAx1.Location(); |
835 | const gp_Dir& Dir0 = theAx1.Direction(); |
836 | //Check new point: is it real solution? |
837 | gp_Pnt OldPonGuide = hguide->Value(theParam); |
838 | gp_Pnt PntOnSurf2 = TheSurfaceTool::Value(AnotherSurf,theU,theV); //old point |
839 | gce_MakePln PlaneBuilder(thePntOnRst, OldPonGuide, PntOnSurf2); |
840 | if (!PlaneBuilder.IsDone()) |
841 | return Standard_False; |
842 | gp_Pln OldPlane = PlaneBuilder.Value(); |
843 | gp_Dir OldDir = OldPlane.Axis().Direction(); |
844 | Standard_Real Angle = OldDir.Angle(Dir0); |
845 | if (Angle > M_PI/2) |
846 | Angle = M_PI - Angle; |
847 | if (Angle > TolAng) |
848 | return Standard_False; |
849 | /////////////////////////////////////// |
850 | //Project the point(theU,theV) on the plane(Pnt0,Dir0) |
851 | gp_Vec aVec(Pnt0, PntOnSurf2); |
852 | gp_Vec aTranslation( (aVec.XYZ() * Dir0.XYZ()) * Dir0.XYZ() ); |
853 | gp_Pnt PntOnPlane = PntOnSurf2.Translated(-aTranslation); |
854 | |
855 | //Check new point again: does point on restriction belong to the plane? |
856 | PlaneBuilder = gce_MakePln(thePntOnRst, Pnt0, PntOnPlane); |
857 | if (!PlaneBuilder.IsDone()) |
858 | return Standard_False; |
859 | gp_Pln NewPlane = PlaneBuilder.Value(); |
860 | const gp_Dir& DirOfNewPlane = NewPlane.Axis().Direction(); |
861 | Angle = Dir0.Angle(DirOfNewPlane); |
862 | if (Angle > M_PI/2) |
863 | Angle = M_PI - Angle; |
864 | if (Angle > TolAng) |
865 | return Standard_False; |
866 | //////////////////////////////////////////////////////////////////////// |
867 | |
868 | //Project the point <PntOnPlane> on the surface 2 |
c22b52d6 |
869 | Extrema_ExtPS projonsurf(PntOnPlane, *AnotherSurf, |
af99433e |
870 | Precision::PConfusion(), Precision::PConfusion(), |
871 | Extrema_ExtFlag_MIN); |
872 | if (projonsurf.IsDone()) |
873 | { |
874 | Standard_Real MinSqDist = Precision::Infinite(); |
875 | Standard_Integer imin = 0; |
876 | for (Standard_Integer ind = 1; ind <= projonsurf.NbExt(); ind++) |
877 | { |
878 | Standard_Real aSqDist = projonsurf.SquareDistance(ind); |
879 | if (aSqDist < MinSqDist) |
880 | { |
881 | MinSqDist = aSqDist; |
882 | imin = ind; |
883 | } |
884 | } |
885 | if (imin) |
886 | { |
887 | Extrema_POnSurf NewPOnSurf2 = projonsurf.Point(imin); |
888 | NewPoint = NewPOnSurf2.Value(); |
889 | NewPOnSurf2.Parameter(NewU, NewV); |
890 | Standard_Real uperiod = (AnotherSurf->IsUPeriodic())? AnotherSurf->UPeriod() : 0.; |
891 | Standard_Real vperiod = (AnotherSurf->IsVPeriodic())? AnotherSurf->VPeriod() : 0.; |
892 | RecadreIfPeriodic(NewU, NewV, theU, theV, |
893 | uperiod, vperiod); |
894 | return Standard_True; |
895 | } |
896 | } |
897 | |
898 | return Standard_False; |
899 | } |