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#include <gce_MakePln.hxx> 16#include <Extrema_ExtPS.hxx> 17#include <Extrema_ExtPC.hxx> 18 19#ifdef DRAW 20#include <DrawTrSurf.hxx> 21#endif 22 23 24static const Standard_Real CosRef3D = 0.88; 25 26static 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} 46 47static 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 98void Blend_Walking::InternalPerform(Blend_Function& Func, 99 Blend_FuncInv& FuncInv, 100 const Standard_Real Bound) 101{ 102 Standard_Real Cosi = 0., Cosi2 = 0.; 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; 116 gp_Vec TgOnGuide, PrevTgOnGuide; 117 gp_Pnt PtOnGuide; 118 hguide->D1(parprec, PtOnGuide, TgOnGuide); 119 PrevTgOnGuide = TgOnGuide; 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; 127 Standard_Integer Index1 = 0, Index2 = 0, nbarc; 128 Standard_Boolean Arrive,recad1,recad2, control; 129 Standard_Boolean Isvtx1 = Standard_False, Isvtx2 = Standard_False, echecrecad; 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 156#ifdef OCCT_DEBUG 157 sectioncalculee = 0; 158 nbcomputedsection++; 159#endif 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 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; 322 gp_Pnt Pnt1, Pnt2; 323 p2d = TheArcTool::Value(recdomain1->Value(),solrst1(1)); 324 sol(1) = p2d.X(); 325 sol(2) = p2d.Y(); 326 Pnt1 = TheSurfaceTool::Value(surf1,sol(1),sol(2)); 327 p2d = TheArcTool::Value(recdomain2->Value(),solrst2(1)); 328 sol(3) = p2d.X(); 329 sol(4) = p2d.Y(); 330 Pnt2 = TheSurfaceTool::Value(surf2,sol(3),sol(4)); 331 const Standard_Real TolProd = 1.e-5; 332 Standard_Real SavedParams [2]; 333 Standard_Boolean SameDirs [2] = {Standard_False, Standard_False}; 334 ChFiDS_ElSpine& theElSpine = hguide->ChangeCurve(); 335 SavedParams[0] = theElSpine.GetSavedFirstParameter(); 336 SavedParams[1] = theElSpine.GetSavedLastParameter(); 337 for (Standard_Integer ind = 0; ind < 2; ind++) 338 { 339 if (!Precision::IsInfinite(SavedParams[ind])) 340 { 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; 363 } 364 } 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; 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); 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 } 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(); 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 } 442 } 443 else { 444 State = Blend_OK; 445 } 446 447 Standard_Boolean testdefl = 1; 448#ifdef OCCT_DEBUG 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 { 468#ifdef OCCT_DEBUG 469 std::cout << "Echec recadrage" << std::endl; 470#endif 471 State = Blend_SamePoints; 472 } 473 } 474 } 475 476#ifdef OCCT_DEBUG 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 } 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 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 } 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 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 } 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 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 } 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 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 } 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 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 725#ifdef OCCT_DEBUG 726 std::cout << " Points confondus dans le cheminement" << std::endl; 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), 733 previousP.Parameter(),tolesp);; 734 if (!previousP.IsTangencyPoint()) { 735 Ext1.SetTangent(previousP.TangentOnS1()); 736 Ext2.SetTangent(previousP.TangentOnS2()); 737 } 738 Arrive = Standard_True; 739 } 740 break; 741 default: 742 break; 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} 757 758Standard_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 770 ChFiDS_ElSpine& theElSpine = hguide->ChangeCurve(); 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 869 Extrema_ExtPS projonsurf(PntOnPlane, AnotherSurf->Surface(), 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} 900