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