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 <stdio.h> 16 17#include <Approx_ParametrizationType.hxx> 18#include <TColStd_Array1OfReal.hxx> 19#include <TColgp_Array1OfPnt.hxx> 20#include <TColgp_Array1OfPnt2d.hxx> 21#include <gp_Pnt.hxx> 22#include <gp_Pnt2d.hxx> 23#include <gp_Vec.hxx> 24#include <gp_Vec2d.hxx> 25#include <TColgp_Array1OfVec.hxx> 26#include <TColgp_Array1OfVec2d.hxx> 27#include <AppParCurves_Constraint.hxx> 28#include <AppParCurves_HArray1OfConstraintCouple.hxx> 29#include <AppParCurves_MultiPoint.hxx> 30#include <Precision.hxx> 31#include <math_IntegerVector.hxx> 32#include <math_Gauss.hxx> 33#include <math_Uzawa.hxx> 34#include <AppParCurves_ConstraintCouple.hxx> 35#include Approx_BSpParLeastSquareOfMyBSplGradient_hxx 36 37#if defined(OCCT_DEBUG) && defined( DRAW ) && !defined( WNT ) 38 39static Standard_Boolean mydebug = Standard_False; 40 41#include <Draw.hxx> 42#include <Draw_Appli.hxx> 43#include <DrawTrSurf.hxx> 44#include <Draw_Text2D.hxx> 45#include <Draw_Text3D.hxx> 46#include <TColStd_Array1OfInteger.hxx> 47#include <Geom_BSplineCurve.hxx> 48#include <Geom2d_BSplineCurve.hxx> 49#include <Geom_Line.hxx> 50#include <Geom2d_Line.hxx> 51#include <Geom_TrimmedCurve.hxx> 52#include <Geom2d_TrimmedCurve.hxx> 53 54 55static void DUMP(const MultiLine& Line) 56{ 57 Standard_Integer i, j, nbP2d, nbP3d, firstP, lastP; 58 firstP = LineTool::FirstPoint(Line); 59 lastP = LineTool::LastPoint(Line); 60 61 nbP3d = LineTool::NbP3d(Line); 62 nbP2d = LineTool::NbP2d(Line); 63 Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d; 64 if (nbP3d == 0) mynbP3d = 1; 65 if (nbP2d == 0) mynbP2d = 1; 66 67 TColgp_Array1OfPnt tabP(1, mynbP3d); 68 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d); 69 TColgp_Array1OfVec TabV(1, mynbP3d); 70 TColgp_Array1OfVec2d TabV2d(1, mynbP2d); 71 Standard_Boolean Ok; 72 Handle(Geom_Line) L3d; 73 Handle(Geom2d_Line) L2d; 74 Handle(Geom_TrimmedCurve) L3dt; 75 Handle(Geom2d_TrimmedCurve) L2dt; 76 Handle(Draw_Text2D) T2D; 77 Handle(Draw_Text3D) T3D; 78 79 char solname[100]; 80 char mytext[10]; 81 82 for (i = firstP; i <= lastP; i++) { 83 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabP, tabP2d); 84 else if (nbP2d != 0) LineTool::Value(Line, i, tabP2d); 85 else if (nbP3d != 0) LineTool::Value(Line, i, tabP); 86 87 for (j = 1; j <= nbP3d; j++) { 88 sprintf(solname, "%s%i%s_%i", "p", j, "3d", i); 89 char* Temp = solname; 90 DrawTrSurf::Set(Temp, tabP(j)); 91 // DrawTrSurf::Set(solname, tabP(j)); 92 if (i == firstP || i == lastP) { 93 sprintf(mytext, "%s%i", " ", i); 94 T3D = new Draw_Text3D(tabP(j), mytext, Draw_vert); 95 dout << T3D; 96 } 97 } 98 for (j = 1; j <= nbP2d; j++) { 99 sprintf(solname, "%s%i%s_%i", "p", j, "2d", i); 100 char* Temp = solname; 101 DrawTrSurf::Set(Temp, tabP2d(j)); 102 // DrawTrSurf::Set(solname, tabP2d(j)); 103 if (i == firstP || i == lastP) { 104 sprintf(mytext, "%s%i", " ", i); 105 T2D = new Draw_Text2D(tabP2d(j), mytext, Draw_vert); 106 dout << T2D; 107 } 108 } 109 110 // le cas des tangentes aux extremites: 111 if (i == firstP || i == lastP) { 112 if (nbP3d != 0 && nbP2d != 0) 113 Ok = LineTool::Tangency(Line, i, TabV, TabV2d); 114 else if (nbP2d != 0) 115 Ok = LineTool::Tangency(Line, i, TabV2d); 116 else if (nbP3d != 0) 117 Ok = LineTool::Tangency(Line, i, TabV); 118 119 if (Ok) { 120 for (j = 1; j <= nbP3d; j++) { 121 sprintf(solname, "%s%i%s_%i", "t", j, "3d", i); 122 L3d = new Geom_Line(tabP(j), gp_Dir(TabV(j))); 123 L3dt = new Geom_TrimmedCurve(L3d, 0.0, 0.3); 124 char* Temp = solname; 125 DrawTrSurf::Set(Temp, L3dt); 126 // DrawTrSurf::Set(solname, L3dt); 127 } 128 for (j = 1; j <= nbP2d; j++) { 129 sprintf(solname, "%s%i%s_%i", "t", j, "2d", i); 130 L2d = new Geom2d_Line(tabP2d(j), gp_Dir2d(TabV2d(j))); 131 L2dt = new Geom2d_TrimmedCurve(L2d, 0.0, 0.3); 132 char* Temp = solname; 133 DrawTrSurf::Set(Temp, L2dt); 134 // DrawTrSurf::Set(solname, L2dt); 135 } 136 } 137 } 138 } 139 dout.Flush(); 140} 141 142 143static void DUMP(const AppParCurves_MultiBSpCurve& C) 144{ 145 static Standard_Integer nbappel = 0; 146 Standard_Integer i, j, nbP2d, nbP3d; 147 Standard_Integer nbpoles = C.NbPoles(); 148 Standard_Integer deg = C.Degree(); 149 const TColStd_Array1OfReal& Knots = C.Knots(); 150 const TColStd_Array1OfInteger& Mults = C.Multiplicities(); 151 152 Handle(Geom_BSplineCurve) BSp; 153 Handle(Geom2d_BSplineCurve) BSp2d; 154 155 TColgp_Array1OfPnt tabPoles(1, nbpoles); 156 TColgp_Array1OfPnt2d tabPoles2d(1, nbpoles); 157 char solname[100]; 158 159 nbappel++; 160 for (i = 1; i <= C.NbCurves(); i++) { 161 if (C.Dimension(i) == 3) { 162 C.Curve(i, tabPoles); 163 BSp = new Geom_BSplineCurve(tabPoles, Knots, Mults, deg); 164 sprintf(solname, "%s%i%s_%i", "c", i, "3d", nbappel); 165 char* Temp = solname; 166 DrawTrSurf::Set(Temp, BSp); 167 // DrawTrSurf::Set(solname, BSp); 168 } 169 else { 170 C.Curve(i, tabPoles2d); 171 BSp2d = new Geom2d_BSplineCurve(tabPoles2d, Knots, Mults, deg); 172 sprintf(solname, "%s%i%s_%i", "c", i, "2d", nbappel); 173 char* Temp = solname; 174 DrawTrSurf::Set(Temp, BSp2d); 175 // DrawTrSurf::Set(solname, BSp2d); 176 } 177 } 178 dout.Flush(); 179} 180 181 182#endif 183 184 185 186 187//======================================================================= 188//function : FirstTangencyVector 189//purpose : 190//======================================================================= 191void Approx_BSplComputeLine::FirstTangencyVector(const MultiLine& Line, 192 const Standard_Integer index, 193 math_Vector& V) 194 const { 195 196 Standard_Integer i, j, nbP2d, nbP3d; 197 nbP3d = LineTool::NbP3d(Line); 198 nbP2d = LineTool::NbP2d(Line); 199 Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d; 200 if (nbP3d == 0) mynbP3d = 1; 201 if (nbP2d == 0) mynbP2d = 1; 202 Standard_Boolean Ok = Standard_False; 203 TColgp_Array1OfVec TabV(1, mynbP3d); 204 TColgp_Array1OfVec2d TabV2d(1, mynbP2d); 205 206 if (nbP3d != 0 && nbP2d != 0) 207 Ok = LineTool::Tangency(Line, index, TabV, TabV2d); 208 else if (nbP2d != 0) 209 Ok = LineTool::Tangency(Line, index, TabV2d); 210 else if (nbP3d != 0) 211 Ok = LineTool::Tangency(Line, index, TabV); 212 213 if (Ok) { 214 if (nbP3d != 0) { 215 j = 1; 216 for (i = TabV.Lower(); i <= TabV.Upper(); i++) { 217 V(j) = TabV(i).X(); 218 V(j + 1) = TabV(i).Y(); 219 V(j + 2) = TabV(i).Z(); 220 j += 3; 221 } 222 } 223 if (nbP2d != 0) { 224 j = nbP3d * 3 + 1; 225 for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) { 226 V(j) = TabV2d(i).X(); 227 V(j + 1) = TabV2d(i).Y(); 228 j += 2; 229 } 230 } 231 } 232 else { 233 234 // recherche d un vecteur tangent par construction d une parabole: 235 AppParCurves_Constraint firstC, lastC; 236 firstC = lastC = AppParCurves_PassPoint; 237 Standard_Integer nbpoles = 3; 238 math_Vector mypar(index, index + 2); 239 Parameters(Line, index, index + 2, mypar); 240 Approx_BSpParLeastSquareOfMyBSplGradient 241 LSQ(Line, index, index + 2, firstC, lastC, mypar, nbpoles); 242 AppParCurves_MultiCurve C = LSQ.BezierValue(); 243 244 gp_Pnt myP; 245 gp_Vec myV; 246 gp_Pnt2d myP2d; 247 gp_Vec2d myV2d; 248 j = 1; 249 for (i = 1; i <= nbP3d; i++) { 250 C.D1(i, 0.0, myP, myV); 251 V(j) = myV.X(); 252 V(j + 1) = myV.Y(); 253 V(j + 2) = myV.Z(); 254 j += 3; 255 } 256 j = nbP3d * 3 + 1; 257 for (i = nbP3d + 1; i <= nbP3d + nbP2d; i++) { 258 C.D1(i, 0.0, myP2d, myV2d); 259 V(j) = myV2d.X(); 260 V(j + 1) = myV2d.Y(); 261 j += 2; 262 } 263 } 264 265} 266 267 268//======================================================================= 269//function : LastTangencyVector 270//purpose : 271//======================================================================= 272void Approx_BSplComputeLine::LastTangencyVector(const MultiLine& Line, 273 const Standard_Integer index, 274 math_Vector& V) 275 const { 276 Standard_Integer i, j, nbP2d, nbP3d; 277 nbP3d = LineTool::NbP3d(Line); 278 nbP2d = LineTool::NbP2d(Line); 279 Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d; 280 if (nbP3d == 0) mynbP3d = 1; 281 if (nbP2d == 0) mynbP2d = 1; 282 Standard_Boolean Ok = Standard_False; 283 TColgp_Array1OfVec TabV(1, mynbP3d); 284 TColgp_Array1OfVec2d TabV2d(1, mynbP2d); 285 286 287 if (nbP3d != 0 && nbP2d != 0) 288 Ok = LineTool::Tangency(Line, index, TabV, TabV2d); 289 else if (nbP2d != 0) 290 Ok = LineTool::Tangency(Line, index, TabV2d); 291 else if (nbP3d != 0) 292 Ok = LineTool::Tangency(Line, index, TabV); 293 294 if (Ok) { 295 if (nbP3d != 0) { 296 j = 1; 297 for (i = TabV.Lower(); i <= TabV.Upper(); i++) { 298 V(j) = TabV(i).X(); 299 V(j + 1) = TabV(i).Y(); 300 V(j + 2) = TabV(i).Z(); 301 j += 3; 302 } 303 } 304 if (nbP2d != 0) { 305 j = nbP3d * 3 + 1; 306 for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) { 307 V(j) = TabV2d(i).X(); 308 V(j + 1) = TabV2d(i).Y(); 309 j += 2; 310 } 311 } 312 } 313 else { 314 315 // recherche d un vecteur tangent par construction d une parabole: 316 AppParCurves_Constraint firstC, lastC; 317 firstC = lastC = AppParCurves_PassPoint; 318 Standard_Integer nbpoles = 3; 319 math_Vector mypar(index - 2, index); 320 Parameters(Line, index - 2, index, mypar); 321 Approx_BSpParLeastSquareOfMyBSplGradient 322 LSQ(Line, index - 2, index, firstC, lastC, mypar, nbpoles); 323 AppParCurves_MultiCurve C = LSQ.BezierValue(); 324 325 gp_Pnt myP; 326 gp_Vec myV; 327 gp_Pnt2d myP2d; 328 gp_Vec2d myV2d; 329 j = 1; 330 for (i = 1; i <= nbP3d; i++) { 331 C.D1(i, 1.0, myP, myV); 332 V(j) = myV.X(); 333 V(j + 1) = myV.Y(); 334 V(j + 2) = myV.Z(); 335 j += 3; 336 } 337 j = nbP3d * 3 + 1; 338 for (i = nbP3d + 1; i <= nbP3d + nbP2d; i++) { 339 C.D1(i, 1.0, myP2d, myV2d); 340 V(j) = myV2d.X(); 341 V(j + 1) = myV2d.Y(); 342 j += 2; 343 } 344 } 345 346} 347 348 349 350//======================================================================= 351//function : SearchFirstLambda 352//purpose : 353//======================================================================= 354Standard_Real Approx_BSplComputeLine:: 355SearchFirstLambda(const MultiLine& Line, 356 const math_Vector& aPar, 357 const TColStd_Array1OfReal& Theknots, 358 const math_Vector& V, 359 const Standard_Integer index) const { 360 361 // dq/dw = lambda* V = (p2-p1)/(u2-u1) 362 363 Standard_Integer nbP2d, nbP3d; 364 gp_Pnt P1, P2; 365 gp_Pnt2d P12d, P22d; 366 nbP3d = LineTool::NbP3d(Line); 367 nbP2d = LineTool::NbP2d(Line); 368 Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d; 369 if (nbP3d == 0) mynbP3d = 1; 370 if (nbP2d == 0) mynbP2d = 1; 371 TColgp_Array1OfPnt tabP1(1, mynbP3d), tabP2(1, mynbP3d); 372 TColgp_Array1OfPnt2d tabP12d(1, mynbP2d), tabP22d(1, mynbP2d); 373 374 375 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP1, tabP12d); 376 else if (nbP2d != 0) LineTool::Value(Line, index, tabP12d); 377 else if (nbP3d != 0) LineTool::Value(Line, index, tabP1); 378 379 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index + 1, tabP2, tabP22d); 380 else if (nbP2d != 0) LineTool::Value(Line, index + 1, tabP22d); 381 else if (nbP3d != 0) LineTool::Value(Line, index + 1, tabP2); 382 383 384 Standard_Real U1 = aPar(index), U2 = aPar(index + 1); 385 Standard_Real lambda, S; 386 Standard_Integer low = V.Lower(); 387 Standard_Integer nbknots = Theknots.Length(); 388 389 if (nbP3d != 0) { 390 P1 = tabP1(1); 391 P2 = tabP2(1); 392 gp_Vec P1P2(P1, P2), myV; 393 myV.SetCoord(V(low), V(low + 1), V(low + 2)); 394 lambda = (P1P2.Magnitude()) / (myV.Magnitude()*(U2 - U1)); 395 S = (P1P2.Dot(myV) > 0.0) ? 1.0 : -1.0; 396 } 397 else { 398 P12d = tabP12d(1); 399 P22d = tabP22d(1); 400 gp_Vec2d P1P2(P12d, P22d), myV; 401 myV.SetCoord(V(low), V(low + 1)); 402 lambda = (P1P2.Magnitude()) / (myV.Magnitude()*(U2 - U1)); 403 S = (P1P2.Dot(myV) > 0.0) ? 1.0 : -1.0; 404 } 405 return ((S*lambda)*(Theknots(2) - Theknots(1)) / (Theknots(nbknots) - Theknots(1))); 406 407} 408 409 410//======================================================================= 411//function : SearchLastLambda 412//purpose : 413//======================================================================= 414Standard_Real Approx_BSplComputeLine:: 415SearchLastLambda(const MultiLine& Line, 416 const math_Vector& aPar, 417 const TColStd_Array1OfReal& Theknots, 418 const math_Vector& V, 419 const Standard_Integer index) const 420 421{ 422 // dq/dw = lambda* V = (p2-p1)/(u2-u1) 423 424 Standard_Integer nbP2d, nbP3d; 425 gp_Pnt P1, P2; 426 gp_Pnt2d P12d, P22d; 427 nbP3d = LineTool::NbP3d(Line); 428 nbP2d = LineTool::NbP2d(Line); 429 Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d; 430 if (nbP3d == 0) mynbP3d = 1; 431 if (nbP2d == 0) mynbP2d = 1; 432 TColgp_Array1OfPnt tabP(1, mynbP3d), tabP2(1, mynbP3d); 433 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d), tabP22d(1, mynbP2d); 434 435 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index - 1, tabP, tabP2d); 436 else if (nbP2d != 0) LineTool::Value(Line, index - 1, tabP2d); 437 else if (nbP3d != 0) LineTool::Value(Line, index - 1, tabP); 438 439 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP2, tabP22d); 440 else if (nbP2d != 0) LineTool::Value(Line, index, tabP22d); 441 else if (nbP3d != 0) LineTool::Value(Line, index, tabP2); 442 443 444 Standard_Real U1 = aPar(index - 1), U2 = aPar(index); 445 Standard_Real lambda, S; 446 Standard_Integer low = V.Lower(); 447 Standard_Integer nbknots = Theknots.Length(); 448 if (nbP3d != 0) { 449 P1 = tabP(1); 450 P2 = tabP2(1); 451 gp_Vec P1P2(P1, P2), myV; 452 myV.SetCoord(V(low), V(low + 1), V(low + 2)); 453 lambda = (P1P2.Magnitude()) / (myV.Magnitude()*(U2 - U1)); 454 S = (P1P2.Dot(myV) > 0.0) ? 1.0 : -1.0; 455 } 456 else { 457 P12d = tabP2d(1); 458 P22d = tabP22d(1); 459 gp_Vec2d P1P2(P12d, P22d), myV; 460 myV.SetCoord(V(low), V(low + 1)); 461 lambda = (P1P2.Magnitude()) / (myV.Magnitude()*(U2 - U1)); 462 S = (P1P2.Dot(myV) > 0.0) ? 1.0 : -1.0; 463 } 464 465 return ((S*lambda)*(Theknots(nbknots) - Theknots(nbknots - 1)) 466 / (Theknots(nbknots) - Theknots(1))); 467} 468 469 470 471//======================================================================= 472//function : Approx_BSplComputeLine 473//purpose : 474//======================================================================= 475Approx_BSplComputeLine::Approx_BSplComputeLine 476(const MultiLine& Line, 477 const math_Vector& Parameters, 478 const Standard_Integer degreemin, 479 const Standard_Integer degreemax, 480 const Standard_Real Tolerance3d, 481 const Standard_Real Tolerance2d, 482 const Standard_Integer NbIterations, 483 const Standard_Boolean cutting, 484 const Standard_Boolean Squares) 485{ 486 myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(), 487 Parameters.Upper()); 488 for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) { 489 myfirstParam->SetValue(i, Parameters(i)); 490 } 491 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2); 492 Par = Approx_IsoParametric; 493 myPeriodic = Standard_False; 494 mydegremin = degreemin; 495 mydegremax = degreemax; 496 mytol3d = Tolerance3d; 497 mytol2d = Tolerance2d; 498 mysquares = Squares; 499 mycut = cutting; 500 myitermax = NbIterations; 501 alldone = Standard_False; 502 mycont = -1; 503 myfirstC = AppParCurves_TangencyPoint; 504 mylastC = AppParCurves_TangencyPoint; 505 myhasknots = Standard_False; 506 myhasmults = Standard_False; 507 currenttol3d = currenttol2d = RealLast(); 508 tolreached = Standard_False; 509 Perform(Line); 510} 511 512 513//======================================================================= 514//function : Approx_BSplComputeLine 515//purpose : 516//======================================================================= 517Approx_BSplComputeLine::Approx_BSplComputeLine 518(const math_Vector& Parameters, 519 const Standard_Integer degreemin, 520 const Standard_Integer degreemax, 521 const Standard_Real Tolerance3d, 522 const Standard_Real Tolerance2d, 523 const Standard_Integer NbIterations, 524 const Standard_Boolean cutting, 525 const Standard_Boolean Squares) 526{ 527 myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(), 528 Parameters.Upper()); 529 for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) { 530 myfirstParam->SetValue(i, Parameters(i)); 531 } 532 myfirstC = AppParCurves_TangencyPoint; 533 mylastC = AppParCurves_TangencyPoint; 534 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2); 535 Par = Approx_IsoParametric; 536 myPeriodic = Standard_False; 537 mydegremin = degreemin; 538 mydegremax = degreemax; 539 mytol3d = Tolerance3d; 540 mytol2d = Tolerance2d; 541 mysquares = Squares; 542 mycut = cutting; 543 myitermax = NbIterations; 544 alldone = Standard_False; 545 myhasknots = Standard_False; 546 myhasmults = Standard_False; 547 mycont = -1; 548 currenttol3d = currenttol2d = RealLast(); 549 tolreached = Standard_False; 550} 551 552//======================================================================= 553//function : Approx_BSplComputeLine 554//purpose : 555//======================================================================= 556Approx_BSplComputeLine::Approx_BSplComputeLine 557(const Standard_Integer degreemin, 558 const Standard_Integer degreemax, 559 const Standard_Real Tolerance3d, 560 const Standard_Real Tolerance2d, 561 const Standard_Integer NbIterations, 562 const Standard_Boolean cutting, 563 const Approx_ParametrizationType parametrization, 564 const Standard_Boolean Squares) 565{ 566 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2); 567 Par = parametrization; 568 myPeriodic = Standard_False; 569 mydegremin = degreemin; 570 mydegremax = degreemax; 571 mytol3d = Tolerance3d; 572 mytol2d = Tolerance2d; 573 mysquares = Squares; 574 mycut = cutting; 575 myitermax = NbIterations; 576 myfirstC = AppParCurves_TangencyPoint; 577 mylastC = AppParCurves_TangencyPoint; 578 alldone = Standard_False; 579 myhasknots = Standard_False; 580 myhasmults = Standard_False; 581 mycont = -1; 582 currenttol3d = currenttol2d = RealLast(); 583 tolreached = Standard_False; 584} 585 586 587//======================================================================= 588//function : Approx_BSplComputeLine 589//purpose : 590//======================================================================= 591Approx_BSplComputeLine::Approx_BSplComputeLine 592(const MultiLine& Line, 593 const Standard_Integer degreemin, 594 const Standard_Integer degreemax, 595 const Standard_Real Tolerance3d, 596 const Standard_Real Tolerance2d, 597 const Standard_Integer NbIterations, 598 const Standard_Boolean cutting, 599 const Approx_ParametrizationType parametrization, 600 const Standard_Boolean Squares) 601{ 602 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2); 603 alldone = Standard_False; 604 mydegremin = degreemin; 605 mydegremax = degreemax; 606 mytol3d = Tolerance3d; 607 mytol2d = Tolerance2d; 608 mysquares = Squares; 609 mycut = cutting; 610 myitermax = NbIterations; 611 Par = parametrization; 612 myPeriodic = Standard_False; 613 myfirstC = AppParCurves_TangencyPoint; 614 mylastC = AppParCurves_TangencyPoint; 615 myhasknots = Standard_False; 616 myhasmults = Standard_False; 617 mycont = -1; 618 currenttol3d = currenttol2d = RealLast(); 619 tolreached = Standard_False; 620 Perform(Line); 621} 622 623 624 625//======================================================================= 626//function : Perform 627//purpose : 628//======================================================================= 629void Approx_BSplComputeLine::Perform(const MultiLine& Line) 630{ 631 632#if defined(OCCT_DEBUG) && defined( DRAW ) && !defined( WNT ) 633 if (mydebug) DUMP(Line); 634#endif 635 636 Standard_Integer i, Thefirstpt, Thelastpt; 637 Standard_Boolean Finish = Standard_False, begin = Standard_True; 638 639 // recherche des vraies contraintes donnees par la Line: 640 FindRealConstraints(Line); 641 642 Thefirstpt = LineTool::FirstPoint(Line); 643 Thelastpt = LineTool::LastPoint(Line); 644 Standard_Integer myfirstpt = Thefirstpt; 645 Standard_Integer mylastpt = Thelastpt; 646 647 AppParCurves_ConstraintCouple myCouple1(myfirstpt, realfirstC); 648 AppParCurves_ConstraintCouple myCouple2(mylastpt, reallastC); 649 myConstraints->SetValue(1, myCouple1); 650 myConstraints->SetValue(2, myCouple2); 651 652 math_Vector TheParam(Thefirstpt, Thelastpt, 0.0); 653 if (myfirstParam.IsNull()) { 654 Parameters(Line, Thefirstpt, Thelastpt, TheParam); 655 } 656 else { 657 for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) { 658 TheParam(i + Thefirstpt - 1) = myfirstParam->Value(i); 659 } 660 } 661 662 myParameters = new TColStd_HArray1OfReal(TheParam.Lower(), TheParam.Upper()); 663 for (i = TheParam.Lower(); i <= TheParam.Upper(); i++) { 664 myParameters->SetValue(i, TheParam(i)); 665 } 666 Standard_Integer nbknots = 2; 667 Standard_Real l; 668 alldone = Standard_False; 669 670 if (!mycut) { 671 672 // cas ou on ne desire pas de noeuds supplementaires. 673 // ================================================== 674 675 if (!myhasknots) { 676 TColStd_Array1OfReal theknots(1, 2); 677 TColStd_Array1OfInteger themults(1, 2); 678 theknots(1) = 0.0; 679 theknots(2) = 1.0; 680 alldone = Compute(Line, myfirstpt, mylastpt, TheParam, theknots, themults); 681 } 682 else { 683 if (!myhasmults) { 684 TColStd_Array1OfInteger themults(1, myknots->Length()); 685 alldone = Compute(Line, myfirstpt, mylastpt, TheParam, 686 myknots->Array1(), themults); 687 } 688 else { 689 alldone = Compute(Line, myfirstpt, mylastpt, TheParam, 690 myknots->Array1(), mymults->ChangeArray1()); 691 } 692 } 693 } 694 else { 695 696 // cas ou on va iterer a partir de noeuds donnes par l''utilisateur 697 // ou a partir d''une bezier. 698 // ================================================================ 699 700 while (!Finish) { 701 702 currenttol3d = currenttol2d = RealLast(); 703 704 if (myhasknots && begin) { 705 706 if (!myhasmults) { 707 708 // 1er cas: l''utilisateur donne des noeuds de depart mais 709 // a nous de fixer les multiplicites en fonction de la 710 // continuite desiree. 711 // ======================================================== 712 713 TColStd_Array1OfInteger TheMults(1, myknots->Length()); 714 alldone = Compute(Line, myfirstpt, mylastpt, TheParam, 715 myknots->Array1(), TheMults); 716 } 717 else { 718 719 // 2eme cas: l''utilisateur donne des noeuds de depart 720 // avec leurs multiplicites. 721 // =================================================== 722 723 alldone = Compute(Line, myfirstpt, mylastpt, TheParam, 724 myknots->Array1(), mymults->ChangeArray1()); 725 } 726 begin = Standard_False; 727 } 728 729 else { 730 731 // 3eme cas: l''utilisateur ne donne aucun noeuds de depart 732 // ======================================================== 733 734 TColStd_Array1OfReal Theknots(1, nbknots); 735 TColStd_Array1OfInteger TheMults(1, nbknots); 736 Theknots(1) = 0.0; 737 Theknots(nbknots) = 1.0; 738 for (i = 2; i <= nbknots - 1; i++) { 739 740 l = (mylastpt - myfirstpt)*Standard_Real(i - 1) 741 / Standard_Real(nbknots - 1); 742 Standard_Integer ll = (Standard_Integer)(l); 743 Standard_Real a = l - ll; 744 Standard_Real p1 = TheParam(ll + myfirstpt); 745 Standard_Real p2 = TheParam(ll + 1 + myfirstpt); 746 Theknots(i) = (1. - a)*p1 + a*p2; 747 } 748 749 alldone = Compute(Line, myfirstpt, mylastpt, TheParam, Theknots, TheMults); 750 751 } 752 753 if (!alldone) nbknots++; 754 else Finish = Standard_True; 755 } 756 } 757 758#if defined(OCCT_DEBUG) && defined( DRAW ) && !defined( WNT ) 759 if (mydebug) DUMP(TheMultiBSpCurve); 760#endif 761 762} 763 764 765 766 767//======================================================================= 768//function : Parameters 769//purpose : 770//======================================================================= 771const TColStd_Array1OfReal& Approx_BSplComputeLine::Parameters() const 772{ 773 return myParameters->Array1(); 774} 775 776 777 778//======================================================================= 779//function : Value 780//purpose : 781//======================================================================= 782const AppParCurves_MultiBSpCurve& Approx_BSplComputeLine::Value() const 783{ 784 return TheMultiBSpCurve; 785} 786 787//======================================================================= 788//function : ChangeValue 789//purpose : 790//======================================================================= 791AppParCurves_MultiBSpCurve& Approx_BSplComputeLine::ChangeValue() 792{ 793 return TheMultiBSpCurve; 794} 795 796//======================================================================= 797//function : Parameters 798//purpose : 799//======================================================================= 800 801void Approx_BSplComputeLine::Parameters(const MultiLine& Line, 802 const Standard_Integer firstP, 803 const Standard_Integer lastP, 804 math_Vector& TheParameters) const 805{ 806 Standard_Integer i, j, nbP2d, nbP3d; 807 Standard_Real dist; 808 const Standard_Integer aNbp = lastP - firstP + 1; 809 810 811 if (aNbp == 2) { 812 TheParameters(firstP) = 0.0; 813 TheParameters(lastP) = 1.0; 814 } 815 else if (Par == Approx_ChordLength || Par == Approx_Centripetal) 816 { 817 nbP3d = LineTool::NbP3d(Line); 818 nbP2d = LineTool::NbP2d(Line); 819 Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d; 820 if (nbP3d == 0) mynbP3d = 1; 821 if (nbP2d == 0) mynbP2d = 1; 822 823 TheParameters(firstP) = 0.0; 824 dist = 0.0; 825 TColgp_Array1OfPnt tabP(1, mynbP3d); 826 TColgp_Array1OfPnt tabPP(1, mynbP3d); 827 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d); 828 TColgp_Array1OfPnt2d tabPP2d(1, mynbP2d); 829 830 for (i = firstP + 1; i <= lastP; i++) 831 { 832 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i - 1, tabP, tabP2d); 833 else if (nbP2d != 0) LineTool::Value(Line, i - 1, tabP2d); 834 else if (nbP3d != 0) LineTool::Value(Line, i - 1, tabP); 835 836 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabPP, tabPP2d); 837 else if (nbP2d != 0) LineTool::Value(Line, i, tabPP2d); 838 else if (nbP3d != 0) LineTool::Value(Line, i, tabPP); 839 dist = 0.0; 840 for (j = 1; j <= nbP3d; j++) 841 { 842 const gp_Pnt &aP1 = tabP(j), 843 &aP2 = tabPP(j); 844 dist += aP2.SquareDistance(aP1); 845 } 846 for (j = 1; j <= nbP2d; j++) 847 { 848 const gp_Pnt2d &aP12d = tabP2d(j), 849 &aP22d = tabPP2d(j); 850 851 dist += aP22d.SquareDistance(aP12d); 852 } 853 854 dist = Sqrt(dist); 855 if (Par == Approx_ChordLength) 856 { 857 TheParameters(i) = TheParameters(i - 1) + dist; 858 } 859 else 860 {// Par == Approx_Centripetal 861 TheParameters(i) = TheParameters(i - 1) + Sqrt(dist); 862 } 863 } 864 for (i = firstP; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP); 865 } 866 else { 867 for (i = firstP; i <= lastP; i++) { 868 TheParameters(i) = (Standard_Real(i) - firstP) / 869 (Standard_Real(lastP - Standard_Real(firstP))); 870 } 871 } 872} 873 874 875//======================================================================= 876//function : Compute 877//purpose : 878//======================================================================= 879Standard_Boolean Approx_BSplComputeLine::Compute(const MultiLine& Line, 880 const Standard_Integer fpt, 881 const Standard_Integer lpt, 882 math_Vector& Para, 883 const TColStd_Array1OfReal& Knots, 884 TColStd_Array1OfInteger& Mults) 885{ 886 Standard_Integer i, deg, nbpoles, multinter; 887 Standard_Boolean mydone; 888 Standard_Real Fv, TheTol3d, TheTol2d, l1, l2; 889 Standard_Integer nbp = lpt - fpt + 1; 890 mylambda1 = 0.0; 891 mylambda2 = 0.0; 892 893 math_Vector aParams(Para.Lower(), Para.Upper()); 894 895 for (deg = mydegremin; deg <= mydegremax; deg++) { 896 897 aParams = Para; 898 899 if (!myhasmults) { 900 Mults(Mults.Lower()) = deg + 1; 901 Mults(Mults.Upper()) = deg + 1; 902 nbpoles = deg + 1; 903 if (mycont == -1) multinter = 1; 904 else multinter = Max(1, deg - mycont); 905 for (i = Mults.Lower() + 1; i <= Mults.Upper() - 1; i++) { 906 Mults(i) = multinter; 907 nbpoles += multinter; 908 } 909 } 910 else { 911 nbpoles = -deg - 1; 912 for (i = Mults.Lower(); i <= Mults.Upper(); i++) { 913 nbpoles += Mults.Value(i); 914 } 915 } 916 917 Standard_Integer nbpolestocompare = nbpoles; 918 if (realfirstC == AppParCurves_TangencyPoint) nbpolestocompare++; 919 if (reallastC == AppParCurves_TangencyPoint) nbpolestocompare++; 920 if (realfirstC == AppParCurves_CurvaturePoint) nbpolestocompare++; 921 if (reallastC == AppParCurves_CurvaturePoint) nbpolestocompare++; 922 if (nbpolestocompare > nbp) { 923 Interpol(Line); 924 tolreached = Standard_True; 925 return Standard_True; 926 } 927 928 AppParCurves_MultiBSpCurve mySCU(nbpoles); 929 930 if (mysquares) { 931 Approx_BSpParLeastSquareOfMyBSplGradient SQ(Line, Knots, Mults, fpt, lpt, 932 realfirstC, reallastC, aParams, nbpoles); 933 mydone = SQ.IsDone(); 934 if (mydone) { 935 mySCU = SQ.BSplineValue(); 936 SQ.Error(Fv, TheTol3d, TheTol2d); 937 } 938 else continue; 939 } 940 else { 941 if (nbpoles != deg + 1) { 942 943 if (deg == mydegremin && (realfirstC >= AppParCurves_TangencyPoint || 944 reallastC >= AppParCurves_TangencyPoint)) { 945 Approx_BSpParLeastSquareOfMyBSplGradient 946 thefitt(Line, Knots, Mults, fpt, lpt, realfirstC, reallastC, aParams, nbpoles); 947 mylambda1 = thefitt.FirstLambda()*deg; 948 mylambda2 = thefitt.LastLambda()*deg; 949 950 } 951 l1 = mylambda1 / deg; 952 l2 = mylambda2 / deg; 953 954 Approx_MyBSplGradient GRAD(Line, fpt, lpt, myConstraints, 955 aParams, Knots, Mults, deg, mytol3d, 956 mytol2d, myitermax, l1, l2); 957 958 mydone = GRAD.IsDone(); 959 if (mydone) { 960 mySCU = GRAD.Value(); 961 TheTol3d = GRAD.MaxError3d(); 962 TheTol2d = GRAD.MaxError2d(); 963 } 964 else continue; 965 } 966 else { 967 Approx_MyGradientbis GRAD2(Line, fpt, lpt, myConstraints, 968 aParams, deg, mytol3d, 969 mytol2d, myitermax); 970 mydone = GRAD2.IsDone(); 971 if (mydone) { 972 if (GRAD2.Value().NbCurves() == 0) 973 continue; 974 mySCU = AppParCurves_MultiBSpCurve(GRAD2.Value(), Knots, Mults); 975 TheTol3d = GRAD2.MaxError3d(); 976 TheTol2d = GRAD2.MaxError2d(); 977 } 978 else continue; 979 } 980 } 981 Standard_Boolean save = Standard_True; 982 983 for (i = aParams.Lower(); i <= aParams.Upper(); i++) { 984 if (aParams(i) <= -0.000001 || aParams(i) >= 1.000001) { 985 save = Standard_False; 986 break; 987 } 988 } 989 990 if (mydone) { 991 if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) { 992 // Stockage de la multicurve approximee. 993 tolreached = Standard_True; 994 TheMultiBSpCurve = mySCU; 995 currenttol3d = TheTol3d; 996 currenttol2d = TheTol2d; 997 if (save) { 998 for (i = aParams.Lower(); i <= aParams.Upper(); i++) { 999 myParameters->SetValue(i, aParams(i)); 1000 } 1001 } 1002 return Standard_True; 1003 } 1004 } 1005 1006 if (TheTol3d <= currenttol3d && TheTol2d <= currenttol2d) { 1007 TheMultiBSpCurve = mySCU; 1008 currenttol3d = TheTol3d; 1009 currenttol2d = TheTol2d; 1010 if (save) { 1011 for (i = aParams.Lower(); i <= aParams.Upper(); i++) { 1012 myParameters->SetValue(i, aParams(i)); 1013 } 1014 } 1015 } 1016 1017 } 1018 1019 return Standard_False; 1020} 1021 1022 1023 1024//======================================================================= 1025//function : SetParameters 1026//purpose : 1027//======================================================================= 1028void Approx_BSplComputeLine::SetParameters(const math_Vector& ThePar) 1029{ 1030 myfirstParam = new TColStd_HArray1OfReal(ThePar.Lower(), 1031 ThePar.Upper()); 1032 for (Standard_Integer i = ThePar.Lower(); i <= ThePar.Upper(); i++) { 1033 myfirstParam->SetValue(i, ThePar(i)); 1034 } 1035} 1036 1037 1038//======================================================================= 1039//function : SetKnots 1040//purpose : 1041//======================================================================= 1042void Approx_BSplComputeLine::SetKnots(const TColStd_Array1OfReal& Knots) 1043{ 1044 myhasknots = Standard_True; 1045 myknots = new TColStd_HArray1OfReal(Knots.Lower(), Knots.Upper()); 1046 for (Standard_Integer i = Knots.Lower(); i <= Knots.Upper(); i++) { 1047 myknots->SetValue(i, Knots(i)); 1048 } 1049} 1050 1051 1052//======================================================================= 1053//function : SetKnotsAndMultiplicities 1054//purpose : 1055//======================================================================= 1056void Approx_BSplComputeLine::SetKnotsAndMultiplicities 1057(const TColStd_Array1OfReal& Knots, 1058 const TColStd_Array1OfInteger& Mults) 1059{ 1060 myhasknots = Standard_True; 1061 myhasmults = Standard_True; 1062 Standard_Integer i; 1063 myknots = new TColStd_HArray1OfReal(Knots.Lower(), Knots.Upper()); 1064 for (i = Knots.Lower(); i <= Knots.Upper(); i++) { 1065 myknots->SetValue(i, Knots(i)); 1066 } 1067 mymults = new TColStd_HArray1OfInteger(Mults.Lower(), Mults.Upper()); 1068 for (i = Mults.Lower(); i <= Mults.Upper(); i++) { 1069 mymults->SetValue(i, Mults(i)); 1070 } 1071} 1072 1073//======================================================================= 1074//function : Init 1075//purpose : 1076//======================================================================= 1077void Approx_BSplComputeLine::Init(const Standard_Integer degreemin, 1078 const Standard_Integer degreemax, 1079 const Standard_Real Tolerance3d, 1080 const Standard_Real Tolerance2d, 1081 const Standard_Integer NbIterations, 1082 const Standard_Boolean cutting, 1083 const Approx_ParametrizationType parametrization, 1084 const Standard_Boolean Squares) 1085{ 1086 mydegremin = degreemin; 1087 mydegremax = degreemax; 1088 mytol3d = Tolerance3d; 1089 mytol2d = Tolerance2d; 1090 Par = parametrization; 1091 mysquares = Squares; 1092 mycut = cutting; 1093 myitermax = NbIterations; 1094} 1095 1096 1097 1098//======================================================================= 1099//function : SetDegrees 1100//purpose : 1101//======================================================================= 1102void Approx_BSplComputeLine::SetDegrees(const Standard_Integer degreemin, 1103 const Standard_Integer degreemax) 1104{ 1105 mydegremin = degreemin; 1106 mydegremax = degreemax; 1107} 1108 1109 1110//======================================================================= 1111//function : SetTolerances 1112//purpose : 1113//======================================================================= 1114void Approx_BSplComputeLine::SetTolerances(const Standard_Real Tolerance3d, 1115 const Standard_Real Tolerance2d) 1116{ 1117 mytol3d = Tolerance3d; 1118 mytol2d = Tolerance2d; 1119} 1120 1121 1122//======================================================================= 1123//function : SetConstraints 1124//purpose : 1125//======================================================================= 1126void Approx_BSplComputeLine::SetConstraints(const AppParCurves_Constraint FirstC, 1127 const AppParCurves_Constraint LastC) 1128{ 1129 myfirstC = FirstC; 1130 mylastC = LastC; 1131} 1132 1133//======================================================================= 1134//function : SetPeriodic 1135//purpose : 1136//======================================================================= 1137void Approx_BSplComputeLine::SetPeriodic(const Standard_Boolean thePeriodic) 1138{ 1139 myPeriodic = thePeriodic; 1140} 1141 1142 1143//======================================================================= 1144//function : IsAllApproximated 1145//purpose : 1146//======================================================================= 1147Standard_Boolean Approx_BSplComputeLine::IsAllApproximated() const 1148{ 1149 return alldone; 1150} 1151 1152//======================================================================= 1153//function : IsToleranceReached 1154//purpose : 1155//======================================================================= 1156Standard_Boolean Approx_BSplComputeLine::IsToleranceReached() const 1157{ 1158 return tolreached; 1159} 1160 1161//======================================================================= 1162//function : Error 1163//purpose : 1164//======================================================================= 1165void Approx_BSplComputeLine::Error(Standard_Real& tol3d, 1166 Standard_Real& tol2d) const 1167{ 1168 tol3d = currenttol3d; 1169 tol2d = currenttol2d; 1170} 1171 1172 1173 1174//======================================================================= 1175//function : SetContinuity 1176//purpose : 1177//======================================================================= 1178void Approx_BSplComputeLine::SetContinuity(const Standard_Integer C) 1179{ 1180 mycont = C; 1181} 1182 1183 1184 1185//======================================================================= 1186//function : FindRealConstraints 1187//purpose : 1188//======================================================================= 1189void Approx_BSplComputeLine::FindRealConstraints(const MultiLine& Line) 1190{ 1191 realfirstC = myfirstC; 1192 reallastC = mylastC; 1193 Standard_Integer nbP2d, nbP3d; 1194 nbP3d = LineTool::NbP3d(Line); 1195 nbP2d = LineTool::NbP2d(Line); 1196 Standard_Boolean Ok = Standard_False; 1197 TColgp_Array1OfVec TabV(1, Max(1, nbP3d)); 1198 TColgp_Array1OfVec2d TabV2d(1, Max(1, nbP2d)); 1199 Standard_Integer Thefirstpt = LineTool::FirstPoint(Line); 1200 Standard_Integer Thelastpt = LineTool::LastPoint(Line); 1201 1202 if (myfirstC >= AppParCurves_TangencyPoint) { 1203 1204 if (nbP3d != 0 && nbP2d != 0) 1205 Ok = LineTool::Tangency(Line, Thefirstpt, TabV, TabV2d); 1206 else if (nbP2d != 0) 1207 Ok = LineTool::Tangency(Line, Thefirstpt, TabV2d); 1208 else if (nbP3d != 0) 1209 Ok = LineTool::Tangency(Line, Thefirstpt, TabV); 1210 1211 realfirstC = AppParCurves_PassPoint; 1212 if (Ok) { 1213 realfirstC = AppParCurves_TangencyPoint; 1214 if (myfirstC == AppParCurves_CurvaturePoint) { 1215 if (nbP3d != 0 && nbP2d != 0) 1216 Ok = LineTool::Tangency(Line, Thefirstpt, TabV, TabV2d); 1217 else if (nbP2d != 0) 1218 Ok = LineTool::Tangency(Line, Thefirstpt, TabV2d); 1219 else if (nbP3d != 0) 1220 Ok = LineTool::Tangency(Line, Thefirstpt, TabV); 1221 if (Ok) { 1222 realfirstC = AppParCurves_CurvaturePoint; 1223 } 1224 } 1225 } 1226 } 1227 1228 1229 if (mylastC >= AppParCurves_TangencyPoint) { 1230 1231 if (nbP3d != 0 && nbP2d != 0) 1232 Ok = LineTool::Tangency(Line, Thelastpt, TabV, TabV2d); 1233 else if (nbP2d != 0) 1234 Ok = LineTool::Tangency(Line, Thelastpt, TabV2d); 1235 else if (nbP3d != 0) 1236 Ok = LineTool::Tangency(Line, Thelastpt, TabV); 1237 1238 reallastC = AppParCurves_PassPoint; 1239 if (Ok) { 1240 reallastC = AppParCurves_TangencyPoint; 1241 if (mylastC == AppParCurves_CurvaturePoint) { 1242 if (nbP3d != 0 && nbP2d != 0) 1243 Ok = LineTool::Tangency(Line, Thelastpt, TabV, TabV2d); 1244 else if (nbP2d != 0) 1245 Ok = LineTool::Tangency(Line, Thelastpt, TabV2d); 1246 else if (nbP3d != 0) 1247 Ok = LineTool::Tangency(Line, Thelastpt, TabV); 1248 if (Ok) { 1249 reallastC = AppParCurves_CurvaturePoint; 1250 } 1251 } 1252 } 1253 } 1254 1255} 1256 1257 1258 1259 1260//======================================================================= 1261//function : Interpol 1262//purpose : 1263//======================================================================= 1264void Approx_BSplComputeLine::Interpol(const MultiLine& Line) 1265{ 1266 Standard_Integer i, Thefirstpt, Thelastpt, deg = 3; 1267 mycont = 2; 1268 Thefirstpt = LineTool::FirstPoint(Line); 1269 Thelastpt = LineTool::LastPoint(Line); 1270 math_Vector TheParam(Thefirstpt, Thelastpt, 0.0); 1271 //Par = Approx_ChordLength; 1272 if (myfirstParam.IsNull()) { 1273 Parameters(Line, Thefirstpt, Thelastpt, TheParam); 1274 } 1275 else { 1276 for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) { 1277 TheParam(i + Thefirstpt - 1) = myfirstParam->Value(i); 1278 } 1279 } 1280 AppParCurves_Constraint Cons = AppParCurves_TangencyPoint; 1281 Standard_Real lambda1, lambda2; 1282 Standard_Real Fv; 1283 1284 // Recherche du nombre de noeuds. 1285 Standard_Integer nbknots, nbpoles, nbpoints; 1286 nbpoints = Thelastpt - Thefirstpt + 1; 1287 1288 if (nbpoints == 2) { 1289 Cons = AppParCurves_NoConstraint; 1290 Standard_Integer mydeg = 1; 1291 Approx_BSpParLeastSquareOfMyBSplGradient 1292 LSQ(Line, Thefirstpt, Thelastpt, Cons, Cons, TheParam, mydeg + 1); 1293 alldone = LSQ.IsDone(); 1294 TColStd_Array1OfReal TheKnots(1, 2); 1295 TColStd_Array1OfInteger TheMults(1, 2); 1296 TheKnots(1) = TheParam(Thefirstpt); TheKnots(2) = TheParam(Thelastpt); 1297 TheMults(1) = TheMults(2) = mydeg + 1; 1298 TheMultiBSpCurve = 1299 AppParCurves_MultiBSpCurve(LSQ.BezierValue(), TheKnots, TheMults); 1300 LSQ.Error(Fv, currenttol3d, currenttol2d); 1301 1302 } 1303 else { 1304 nbpoles = nbpoints + 2; 1305 nbknots = nbpoints; 1306 1307 // Resolution: 1308 TColStd_Array1OfReal Theknots(1, nbknots); 1309 Theknots(1) = TheParam(Thefirstpt); 1310 Theknots(nbknots) = TheParam(Thelastpt); 1311 TColStd_Array1OfInteger TheMults(1, nbknots); 1312 TheMults(1) = deg + 1; 1313 TheMults(nbknots) = deg + 1; 1314 1315 Standard_Integer low = TheParam.Lower(); 1316 for (i = 2; i <= nbknots - 1; i++) { 1317 Theknots(i) = TheParam(i + low - 1); 1318 TheMults(i) = 1; 1319 } 1320 1321 1322 Standard_Integer nbP = 3 * LineTool::NbP3d(Line) + 2 * LineTool::NbP2d(Line); 1323 math_Vector V1(1, nbP), V2(1, nbP); 1324 1325 if (nbpoints == 3 || nbpoints == 4) { 1326 FirstTangencyVector(Line, Thefirstpt, V1); 1327 lambda1 = SearchFirstLambda(Line, TheParam, Theknots, V1, Thefirstpt); 1328 1329 LastTangencyVector(Line, Thelastpt, V2); 1330 lambda2 = SearchLastLambda(Line, TheParam, Theknots, V2, Thelastpt); 1331 1332 lambda1 = lambda1 / deg; 1333 lambda2 = lambda2 / deg; 1334 } 1335 else { 1336 Standard_Integer nnpol, nnp = Min(nbpoints, 9); 1337 nnpol = nnp; 1338 Standard_Integer lastp = Min(Thelastpt, Thefirstpt + nnp - 1); 1339 Standard_Real U; 1340 Approx_BSpParLeastSquareOfMyBSplGradient 1341 SQ1(Line, Thefirstpt, lastp, Cons, Cons, nnpol); 1342 1343 math_Vector P1(Thefirstpt, lastp); 1344 for (i = Thefirstpt; i <= lastp; i++) P1(i) = TheParam(i); 1345 SQ1.Perform(P1); 1346 const AppParCurves_MultiCurve& C1 = SQ1.BezierValue(); 1347 U = 0.0; 1348 TangencyVector(Line, C1, U, V1); 1349 1350 Standard_Integer firstp = Max(Thefirstpt, Thelastpt - nnp + 1); 1351 1352 if (firstp == Thefirstpt && lastp == Thelastpt) { 1353 U = 1.0; 1354 TangencyVector(Line, C1, U, V2); 1355 } 1356 else { 1357 Approx_BSpParLeastSquareOfMyBSplGradient 1358 SQ2(Line, firstp, Thelastpt, Cons, Cons, nnpol); 1359 1360 math_Vector P2(firstp, Thelastpt); 1361 for (i = firstp; i <= Thelastpt; i++) P2(i) = TheParam(i); 1362 SQ2.Perform(P2); 1363 const AppParCurves_MultiCurve& C2 = SQ2.BezierValue(); 1364 U = 1.0; 1365 TangencyVector(Line, C2, U, V2); 1366 } 1367 1368 1369 lambda1 = 1. / deg; 1370 lambda1 = lambda1*(Theknots(2) - Theknots(1)) 1371 / (Theknots(nbknots) - Theknots(1)); 1372 lambda2 = 1. / deg; 1373 lambda2 = lambda2*(Theknots(nbknots) - Theknots(nbknots - 1)) 1374 / (Theknots(nbknots) - Theknots(1)); 1375 1376 } 1377 1378 if (myPeriodic) 1379 { 1380 V1 = 0.5 * (V1 + V2); 1381 V2 = V1; 1382 } 1383 1384 Approx_BSpParLeastSquareOfMyBSplGradient 1385 SQ(Line, Theknots, TheMults, Thefirstpt, Thelastpt, 1386 Cons, Cons, nbpoles); 1387 1388 SQ.Perform(TheParam, V1, V2, lambda1, lambda2); 1389 alldone = SQ.IsDone(); 1390 TheMultiBSpCurve = SQ.BSplineValue(); 1391 SQ.Error(Fv, currenttol3d, currenttol2d); 1392 tolreached = Standard_True; 1393 } 1394 myParameters = new TColStd_HArray1OfReal(TheParam.Lower(), TheParam.Upper()); 1395 for (i = TheParam.Lower(); i <= TheParam.Upper(); i++) { 1396 myParameters->SetValue(i, TheParam(i)); 1397 } 1398} 1399 1400 1401//======================================================================= 1402//function : TangencyVector 1403//purpose : 1404//======================================================================= 1405void Approx_BSplComputeLine::TangencyVector( 1406 const MultiLine& Line, 1407 const AppParCurves_MultiCurve& C, 1408 const Standard_Real U, 1409 math_Vector& V) const 1410{ 1411 1412 Standard_Integer i, j, nbP2d, nbP3d; 1413 nbP3d = LineTool::NbP3d(Line); 1414 nbP2d = LineTool::NbP2d(Line); 1415 1416 gp_Pnt myP; 1417 gp_Vec myV; 1418 gp_Pnt2d myP2d; 1419 gp_Vec2d myV2d; 1420 j = 1; 1421 for (i = 1; i <= nbP3d; i++) { 1422 C.D1(i, U, myP, myV); 1423 V(j) = myV.X(); 1424 V(j + 1) = myV.Y(); 1425 V(j + 2) = myV.Z(); 1426 j += 3; 1427 } 1428 j = nbP3d * 3 + 1; 1429 for (i = nbP3d + 1; i <= nbP3d + nbP2d; i++) { 1430 C.D1(i, U, myP2d, myV2d); 1431 V(j) = myV2d.X(); 1432 V(j + 1) = myV2d.Y(); 1433 j += 2; 1434 } 1435 1436} 1437 1438