1 // File Approx_ComputeLine.gxx
3 #include <Approx_ParametrizationType.hxx>
4 #include Approx_ParLeastSquareOfMyGradient_hxx
5 #include <TColStd_Array1OfReal.hxx>
6 #include <TColgp_Array1OfPnt.hxx>
7 #include <TColgp_Array1OfPnt2d.hxx>
9 #include <gp_Pnt2d.hxx>
11 #include <gp_Vec2d.hxx>
12 #include <TColgp_Array1OfVec.hxx>
13 #include <TColgp_Array1OfVec2d.hxx>
14 #include <AppParCurves_Constraint.hxx>
15 #include <AppParCurves_HArray1OfConstraintCouple.hxx>
16 #include <AppParCurves_MultiPoint.hxx>
17 #include <Precision.hxx>
18 #include <math_IntegerVector.hxx>
19 #include <math_Gauss.hxx>
20 #include <math_Uzawa.hxx>
21 #include <Approx_MCurvesToBSpCurve.hxx>
22 #include <AppParCurves_ConstraintCouple.hxx>
27 static Standard_Boolean mydebug = Standard_False;
29 #include <Geom_BezierCurve.hxx>
30 #include <Geom2d_BezierCurve.hxx>
32 #include <DrawTrSurf.hxx>
34 #include <Draw_Appli.hxx>
36 static void DUMP(const MultiLine& Line)
38 Standard_Integer i, j, nbP2d, nbP3d, firstP, lastP;
42 firstP = LineTool::FirstPoint(Line);
43 lastP = LineTool::LastPoint(Line);
45 nbP3d = LineTool::NbP3d(Line);
46 nbP2d = LineTool::NbP2d(Line);
47 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
48 if (nbP3d == 0) mynbP3d = 1;
49 if (nbP2d == 0) mynbP2d = 1;
51 TColgp_Array1OfPnt tabP(1, mynbP3d);
52 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
54 cout <<"DUMP de la MultiLine entre "<<firstP <<" et "<<lastP<<": "<<endl;
55 for (i = firstP; i <= lastP; i++) {
56 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabP, tabP2d);
57 else if (nbP2d != 0) LineTool::Value(Line, i, tabP2d);
58 else if (nbP3d != 0) LineTool::Value(Line, i, tabP);
60 cout << "point "<<i<<":"<< endl;
61 for (j = 1; j <= nbP3d; j++) {
63 cout <<P1.X()<<" "<<P1.Y()<<" "<<P1.Z()<<endl;
65 for (j = 1; j <= nbP2d; j++) {
67 cout <<P12d.X()<<" "<<P12d.Y()<<endl;
74 static void DUMP(const AppParCurves_MultiCurve& C) {
75 static Standard_Integer nbappel = 0;
77 Standard_Integer nbpoles = C.NbPoles();
78 Standard_Integer deg = C.Degree();
80 Handle(Geom_BezierCurve) BSp;
81 Handle(Geom2d_BezierCurve) BSp2d;
83 TColgp_Array1OfPnt tabPoles(1, nbpoles);
84 TColgp_Array1OfPnt2d tabPoles2d(1, nbpoles);
88 for (i = 1; i <= C.NbCurves(); i++) {
89 if (C.Dimension(i) == 3) {
91 BSp = new Geom_BezierCurve(tabPoles);
92 sprintf(solname, "%s%i%s_%i", "c", i, "3d", nbappel);
95 DrawTrSurf::Set(Temp, BSp);
96 // DrawTrSurf::Set(solname, BSp);
100 C.Curve(i, tabPoles2d);
101 BSp2d = new Geom2d_BezierCurve(tabPoles2d);
102 sprintf(solname, "%s%i%s_%i", "c", i, "2d", nbappel);
104 char* Temp = solname;
105 DrawTrSurf::Set(Temp, BSp2d);
106 // DrawTrSurf::Set(solname, BSp2d);
118 void Approx_ComputeLine::FirstTangencyVector(const MultiLine& Line,
119 const Standard_Integer index,
120 math_Vector& V) const
123 Standard_Integer i, j, nbP2d, nbP3d;
124 nbP3d = LineTool::NbP3d(Line);
125 nbP2d = LineTool::NbP2d(Line);
126 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
127 if (nbP3d == 0) mynbP3d = 1;
128 if (nbP2d == 0) mynbP2d = 1;
129 Standard_Boolean Ok=Standard_False;
130 TColgp_Array1OfVec TabV(1, mynbP3d);
131 TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
133 if (nbP3d != 0 && nbP2d != 0)
134 Ok = LineTool::Tangency(Line, index, TabV, TabV2d);
136 Ok = LineTool::Tangency(Line, index, TabV2d);
138 Ok = LineTool::Tangency(Line, index, TabV);
143 for (i = TabV.Lower(); i <= TabV.Upper(); i++) {
145 V(j+1) = TabV(i).Y();
146 V(j+2) = TabV(i).Z();
152 for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) {
153 V(j) = TabV2d(i).X();
154 V(j+1) = TabV2d(i).Y();
161 // recherche d un vecteur tangent par construction d une parabole:
162 AppParCurves_Constraint firstC, lastC;
163 firstC = lastC = AppParCurves_PassPoint;
164 Standard_Integer nbpoles = 3;
165 math_Vector mypar(index, index+2);
166 Parameters(Line, index, index+2, mypar);
167 Approx_ParLeastSquareOfMyGradient
168 LSQ(Line, index, index+2, firstC, lastC, mypar, nbpoles);
169 AppParCurves_MultiCurve C = LSQ.BezierValue();
176 for (i = 1; i <= nbP3d; i++) {
177 C.D1(i, 0.0, myP, myV);
184 for (i = nbP3d+1; i <= nbP3d+nbP2d; i++) {
185 C.D1(i, 0.0, myP2d, myV2d);
194 void Approx_ComputeLine::LastTangencyVector(const MultiLine& Line,
195 const Standard_Integer index,
196 math_Vector& V) const
198 Standard_Integer i, j, nbP2d, nbP3d;
199 nbP3d = LineTool::NbP3d(Line);
200 nbP2d = LineTool::NbP2d(Line);
201 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
202 if (nbP3d == 0) mynbP3d = 1;
203 if (nbP2d == 0) mynbP2d = 1;
204 Standard_Boolean Ok=Standard_False;
205 TColgp_Array1OfVec TabV(1, mynbP3d);
206 TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
209 if (nbP3d != 0 && nbP2d != 0)
210 Ok = LineTool::Tangency(Line, index, TabV, TabV2d);
212 Ok = LineTool::Tangency(Line, index, TabV2d);
214 Ok = LineTool::Tangency(Line, index, TabV);
219 for (i = TabV.Lower(); i <= TabV.Upper(); i++) {
221 V(j+1) = TabV(i).Y();
222 V(j+2) = TabV(i).Z();
228 for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) {
229 V(j) = TabV2d(i).X();
230 V(j+1) = TabV2d(i).Y();
237 // recherche d un vecteur tangent par construction d une parabole:
238 AppParCurves_Constraint firstC, lastC;
239 firstC = lastC = AppParCurves_PassPoint;
240 Standard_Integer nbpoles = 3;
241 math_Vector mypar(index-2, index);
242 Parameters(Line, index-2, index, mypar);
243 Approx_ParLeastSquareOfMyGradient
244 LSQ(Line, index-2, index, firstC, lastC, mypar, nbpoles);
245 AppParCurves_MultiCurve C = LSQ.BezierValue();
252 for (i = 1; i <= nbP3d; i++) {
253 C.D1(i, 1.0, myP, myV);
260 for (i = nbP3d+1; i <= nbP3d+nbP2d; i++) {
261 C.D1(i, 1.0, myP2d, myV2d);
272 Standard_Real Approx_ComputeLine::
273 SearchFirstLambda(const MultiLine& Line,
274 const math_Vector& TheParam,
275 const math_Vector& V,
276 const Standard_Integer index) const
279 // dq/dw = lambda* V = (p2-p1)/(u2-u1)
281 Standard_Integer nbP2d, nbP3d;
284 nbP3d = LineTool::NbP3d(Line);
285 nbP2d = LineTool::NbP2d(Line);
286 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
287 if (nbP3d == 0) mynbP3d = 1;
288 if (nbP2d == 0) mynbP2d = 1;
289 TColgp_Array1OfPnt tabP1(1, mynbP3d), tabP2(1, mynbP3d);
290 TColgp_Array1OfPnt2d tabP12d(1, mynbP2d), tabP22d(1, mynbP2d);
293 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP1, tabP12d);
294 else if (nbP2d != 0) LineTool::Value(Line, index, tabP12d);
295 else if (nbP3d != 0) LineTool::Value(Line, index, tabP1);
297 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index+1, tabP2, tabP22d);
298 else if (nbP2d != 0) LineTool::Value(Line, index+1, tabP22d);
299 else if (nbP3d != 0) LineTool::Value(Line, index+1, tabP2);
302 Standard_Real U1 = TheParam(index), U2 = TheParam(index+1);
303 Standard_Real lambda, S;
304 Standard_Integer low = V.Lower();
309 gp_Vec P1P2(P1, P2), myV;
310 myV.SetCoord(V(low), V(low+1), V(low+2));
311 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
312 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
317 gp_Vec2d P1P2(P12d, P22d), myV;
318 myV.SetCoord(V(low), V(low+1));
319 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
320 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
327 Standard_Real Approx_ComputeLine::
328 SearchLastLambda(const MultiLine& Line,
329 const math_Vector& TheParam,
330 const math_Vector& V,
331 const Standard_Integer index) const
333 // dq/dw = lambda* V = (p2-p1)/(u2-u1)
335 Standard_Integer nbP2d, nbP3d;
338 nbP3d = LineTool::NbP3d(Line);
339 nbP2d = LineTool::NbP2d(Line);
340 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
341 if (nbP3d == 0) mynbP3d = 1;
342 if (nbP2d == 0) mynbP2d = 1;
343 TColgp_Array1OfPnt tabP(1, mynbP3d), tabP2(1, mynbP3d);
344 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d), tabP22d(1, mynbP2d);
346 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index-1, tabP, tabP2d);
347 else if (nbP2d != 0) LineTool::Value(Line, index-1, tabP2d);
348 else if (nbP3d != 0) LineTool::Value(Line, index-1, tabP);
350 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP2, tabP22d);
351 else if (nbP2d != 0) LineTool::Value(Line, index, tabP22d);
352 else if (nbP3d != 0) LineTool::Value(Line, index, tabP2);
355 Standard_Real U1 = TheParam(index-1), U2 = TheParam(index);
356 Standard_Real lambda, S;
357 Standard_Integer low = V.Lower();
362 gp_Vec P1P2(P1, P2), myV;
363 myV.SetCoord(V(low), V(low+1), V(low+2));
364 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
365 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
370 gp_Vec2d P1P2(P12d, P22d), myV;
371 myV.SetCoord(V(low), V(low+1));
372 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
373 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
381 Approx_ComputeLine::Approx_ComputeLine
382 (const MultiLine& Line,
383 const math_Vector& Parameters,
384 const Standard_Integer degreemin,
385 const Standard_Integer degreemax,
386 const Standard_Real Tolerance3d,
387 const Standard_Real Tolerance2d,
388 const Standard_Integer NbIterations,
389 const Standard_Boolean cutting,
390 const Standard_Boolean Squares)
392 myIsClear (Standard_False)
394 myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(),
396 for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) {
397 myfirstParam->SetValue(i, Parameters(i));
399 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
400 Par = Approx_IsoParametric;
401 mydegremin = degreemin;
402 mydegremax = degreemax;
403 mytol3d = Tolerance3d;
404 mytol2d = Tolerance2d;
407 myitermax = NbIterations;
408 alldone = Standard_False;
409 myfirstC = AppParCurves_TangencyPoint;
410 mylastC = AppParCurves_TangencyPoint;
415 Approx_ComputeLine::Approx_ComputeLine
416 (const math_Vector& Parameters,
417 const Standard_Integer degreemin,
418 const Standard_Integer degreemax,
419 const Standard_Real Tolerance3d,
420 const Standard_Real Tolerance2d,
421 const Standard_Integer NbIterations,
422 const Standard_Boolean cutting,
423 const Standard_Boolean Squares)
425 myIsClear (Standard_False)
427 myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(),
429 for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) {
430 myfirstParam->SetValue(i, Parameters(i));
432 myfirstC = AppParCurves_TangencyPoint;
433 mylastC = AppParCurves_TangencyPoint;
434 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
435 Par = Approx_IsoParametric;
436 mydegremin = degreemin;
437 mydegremax = degreemax;
438 mytol3d = Tolerance3d;
439 mytol2d = Tolerance2d;
442 myitermax = NbIterations;
443 alldone = Standard_False;
446 Approx_ComputeLine::Approx_ComputeLine
447 (const Standard_Integer degreemin,
448 const Standard_Integer degreemax,
449 const Standard_Real Tolerance3d,
450 const Standard_Real Tolerance2d,
451 const Standard_Integer NbIterations,
452 const Standard_Boolean cutting,
453 const Approx_ParametrizationType parametrization,
454 const Standard_Boolean Squares)
456 myIsClear (Standard_False)
458 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
459 Par = parametrization;
460 mydegremin = degreemin;
461 mydegremax = degreemax;
462 mytol3d = Tolerance3d;
463 mytol2d = Tolerance2d;
466 myitermax = NbIterations;
467 myfirstC = AppParCurves_TangencyPoint;
468 mylastC = AppParCurves_TangencyPoint;
469 alldone = Standard_False;
473 Approx_ComputeLine::Approx_ComputeLine
474 (const MultiLine& Line,
475 const Standard_Integer degreemin,
476 const Standard_Integer degreemax,
477 const Standard_Real Tolerance3d,
478 const Standard_Real Tolerance2d,
479 const Standard_Integer NbIterations,
480 const Standard_Boolean cutting,
481 const Approx_ParametrizationType parametrization,
482 const Standard_Boolean Squares)
484 myIsClear (Standard_False)
486 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
487 alldone = Standard_False;
488 mydegremin = degreemin;
489 mydegremax = degreemax;
490 mytol3d = Tolerance3d;
491 mytol2d = Tolerance2d;
494 myitermax = NbIterations;
495 Par = parametrization;
496 myfirstC = AppParCurves_TangencyPoint;
497 mylastC = AppParCurves_TangencyPoint;
504 void Approx_ComputeLine::Perform(const MultiLine& Line)
507 if (mydebug) DUMP(Line);
511 myMultiCurves.Clear();
517 else myIsClear = Standard_False;
519 Standard_Integer i, nbp, Thefirstpt, Thelastpt, oldlastpt;
520 Standard_Boolean Finish = Standard_False,
521 begin = Standard_True, Ok = Standard_False,
522 GoUp = Standard_False, Interpol;
523 Standard_Real thetol3d, thetol2d;
524 Approx_Status MyStatus;
525 // gp_Vec V13d, V23d;
527 Thefirstpt = LineTool::FirstPoint(Line);
528 Thelastpt = LineTool::LastPoint(Line);
529 Standard_Integer myfirstpt = Thefirstpt;
530 Standard_Integer mylastpt = Thelastpt;
532 AppParCurves_ConstraintCouple myCouple1(myfirstpt, myfirstC);
533 AppParCurves_ConstraintCouple myCouple2(mylastpt, mylastC);
534 myConstraints->SetValue(1, myCouple1);
535 myConstraints->SetValue(2, myCouple2);
537 math_Vector TheParam(Thefirstpt, Thelastpt);
541 if(myfirstParam.IsNull()) {
542 Parameters(Line, Thefirstpt, Thelastpt, TheParam);
545 for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) {
546 TheParam(i+Thefirstpt-1) = myfirstParam->Value(i);
549 TheMultiCurve = AppParCurves_MultiCurve();
550 alldone = Compute(Line, myfirstpt, mylastpt, TheParam, thetol3d, thetol2d);
551 if(!alldone && TheMultiCurve.NbCurves() > 0) {
553 if (mydebug) DUMP(TheMultiCurve);
555 myMultiCurves.Append(TheMultiCurve);
556 Tolers3d.Append(currenttol3d);
557 Tolers2d.Append(currenttol2d);
558 Handle(TColStd_HArray1OfReal) ThePar = new TColStd_HArray1OfReal(myfirstpt, mylastpt);
559 for (i = myfirstpt; i <= mylastpt; i++) {
560 ThePar->SetValue(i, myParameters->Value(i));
562 myPar.Append(ThePar);
567 oldlastpt = mylastpt;
568 // Gestion du decoupage de la multiline pour approximer:
572 // Calcul de la partie a approximer.
573 myfirstpt = mylastpt;
574 mylastpt = Thelastpt;
575 if (myfirstpt == Thelastpt) {
576 Finish = Standard_True;
577 alldone = Standard_True;
582 nbp = mylastpt - myfirstpt + 1;
583 MyStatus = LineTool::WhatStatus(Line, myfirstpt, mylastpt);
584 if (MyStatus == Approx_NoPointsAdded && nbp <= mydegremax+1) {
585 Interpol = ComputeCurve(Line, myfirstpt, mylastpt);
587 if (mylastpt == Thelastpt) {
588 Finish = Standard_True;
589 alldone = Standard_True;
594 mylastpt = Standard_Integer((myfirstpt + mylastpt)/2);
597 GoUp = Standard_False;
600 // Verification du nombre de points restants par rapport au degre
602 // ==============================================================
603 nbp = mylastpt - myfirstpt + 1;
604 MyStatus = LineTool::WhatStatus(Line, myfirstpt, mylastpt);
605 if (nbp <= mydegremax+5 ) {
606 // Rajout necessaire de points si possible.
607 // ========================================
608 GoUp = Standard_False;
610 Standard_Boolean FailOnPointsAdded = Standard_False;
611 if (MyStatus == Approx_PointsAdded) {
612 // Appel recursif du decoupage:
613 GoUp = Standard_True;
615 MultiLine OtherLine =LineTool::MakeMLBetween(Line, myfirstpt,
618 Standard_Integer nbpdsotherligne = LineTool::FirstPoint(OtherLine)
619 -LineTool::LastPoint(OtherLine);
621 //-- Si MakeML a echoue on retourne une ligne vide
622 if ((nbpdsotherligne == 0) || myMultiLineNb >= 3)
624 FailOnPointsAdded = Standard_True;
625 //-- cout<<" ** ApproxComputeLine MakeML Echec ** LBR lbr "<<endl;
626 if (myfirstpt == mylastpt) break; // Pour etre sur de ne pas
627 // planter la station !!
628 myCouple1.SetIndex(myfirstpt);
629 myCouple2.SetIndex(mylastpt);
630 myConstraints->SetValue(1, myCouple1);
631 myConstraints->SetValue(2, myCouple2);
633 math_Vector Param(myfirstpt, mylastpt);
634 Approx_ParametrizationType SavePar = Par;
635 Par = Approx_IsoParametric;
636 Parameters(Line, myfirstpt, mylastpt, Param);
637 TheMultiCurve = AppParCurves_MultiCurve();
638 Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d);
641 Standard_Real tt3d = currenttol3d, tt2d = currenttol2d;
642 Handle(TColStd_HArray1OfReal) saveParameters = myParameters;
643 AppParCurves_MultiCurve saveMultiCurve = TheMultiCurve;
645 if(SavePar != Approx_IsoParametric)
648 Par = Approx_ChordLength;
650 Parameters(Line, myfirstpt, mylastpt, Param);
651 Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d);
653 if (!Ok && tt3d <= currenttol3d && tt2d <= currenttol2d) {
654 currenttol3d = tt3d; currenttol2d = tt2d;
655 myParameters = saveParameters;
656 TheMultiCurve = saveMultiCurve;
661 oldlastpt = mylastpt;
663 tolreached = Standard_False;
664 if (TheMultiCurve.NbCurves() == 0) {
665 myMultiCurves.Clear();
669 if (mydebug) DUMP(TheMultiCurve);
671 myMultiCurves.Append(TheMultiCurve);
672 Tolers3d.Append(currenttol3d);
673 Tolers2d.Append(currenttol2d);
675 Handle(TColStd_HArray1OfReal) ThePar = new TColStd_HArray1OfReal(myfirstpt, oldlastpt);
676 for (i = myfirstpt; i <= oldlastpt; i++) {
677 ThePar->SetValue(i, myParameters->Value(i));
679 myPar.Append(ThePar);
681 myfirstpt = oldlastpt;
682 mylastpt = Thelastpt;
687 myIsClear = Standard_True;
690 myfirstpt = mylastpt;
691 mylastpt = Thelastpt;
695 if (MyStatus == Approx_NoPointsAdded && !begin) {
696 // On rend la meilleure approximation obtenue precedemment.
697 // ========================================================
698 GoUp = Standard_True;
699 tolreached = Standard_False;
700 if (TheMultiCurve.NbCurves() == 0) {
701 myMultiCurves.Clear();
705 if (mydebug) DUMP(TheMultiCurve);
707 myMultiCurves.Append(TheMultiCurve);
708 Tolers3d.Append(currenttol3d);
709 Tolers2d.Append(currenttol2d);
711 Handle(TColStd_HArray1OfReal) ThePar = new TColStd_HArray1OfReal(myfirstpt, oldlastpt);
712 for (i = myfirstpt; i <= oldlastpt; i++) {
713 ThePar->SetValue(i, myParameters->Value(i));
715 myPar.Append(ThePar);
717 myfirstpt = oldlastpt;
718 mylastpt = Thelastpt;
721 else if (MyStatus == Approx_NoApproximation) {
722 // On ne fait pas d approximation entre myfirstpt et mylastpt.
723 // ===========================================================
724 // On stocke pour pouvoir en informer l utilisateur.
725 GoUp = Standard_True;
726 myfirstpt = mylastpt;
727 mylastpt = Thelastpt;
731 if (myfirstpt == Thelastpt) {
732 Finish = Standard_True;
733 alldone = Standard_True;
737 if (myfirstpt == mylastpt) break; // Pour etre sur de ne pas
738 // planter la station !!
739 myCouple1.SetIndex(myfirstpt);
740 myCouple2.SetIndex(mylastpt);
741 myConstraints->SetValue(1, myCouple1);
742 myConstraints->SetValue(2, myCouple2);
744 // Calcul des parametres sur ce nouvel intervalle.
745 // On recupere les parametres initiaux lors du decoupage.
747 math_Vector Param(myfirstpt, mylastpt);
749 if(myfirstParam.IsNull()) {
750 Parameters(Line, myfirstpt, mylastpt, Param);
753 for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) {
754 Param(i) = myfirstParam->Value(i);
756 myfirstParam.Nullify();
759 begin = Standard_False;
762 Standard_Real pfirst = TheParam.Value(myfirstpt);
763 Standard_Real plast = TheParam.Value(mylastpt);
764 for (i = myfirstpt; i <= mylastpt; i++) {
765 Param(i) = (TheParam.Value(i)-pfirst)/(plast-pfirst);
769 TheMultiCurve = AppParCurves_MultiCurve();
770 Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d);
779 const TColStd_Array1OfReal& Approx_ComputeLine::Parameters(const Standard_Integer Index) const
781 return (myPar.Value(Index))->Array1();
785 Standard_Integer Approx_ComputeLine::NbMultiCurves()const
787 return myMultiCurves.Length();
790 AppParCurves_MultiCurve& Approx_ComputeLine::ChangeValue(const Standard_Integer Index)
792 return myMultiCurves.ChangeValue(Index);
796 const AppParCurves_MultiCurve& Approx_ComputeLine::Value(const Standard_Integer Index)
799 return myMultiCurves.Value(Index);
803 const AppParCurves_MultiBSpCurve& Approx_ComputeLine::SplineValue()
805 Approx_MCurvesToBSpCurve Trans;
806 Trans.Perform(myMultiCurves);
807 myspline = Trans.Value();
815 void Approx_ComputeLine::Parameters(const MultiLine& Line,
816 const Standard_Integer firstP,
817 const Standard_Integer lastP,
818 math_Vector& TheParameters) const
820 Standard_Integer i, j, Nbp, nbP2d, nbP3d;
824 Nbp = lastP-firstP+1;
826 if (Par == Approx_ChordLength || Par == Approx_Centripetal) {
827 nbP3d = LineTool::NbP3d(Line);
828 nbP2d = LineTool::NbP2d(Line);
829 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
830 if (nbP3d == 0) mynbP3d = 1;
831 if (nbP2d == 0) mynbP2d = 1;
833 TheParameters(firstP) = 0.0;
835 TColgp_Array1OfPnt tabP(1, mynbP3d);
836 TColgp_Array1OfPnt tabPP(1, mynbP3d);
837 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
838 TColgp_Array1OfPnt2d tabPP2d(1, mynbP2d);
840 for (i = firstP+1; i <= lastP; i++) {
841 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i-1, tabP, tabP2d);
842 else if (nbP2d != 0) LineTool::Value(Line, i-1, tabP2d);
843 else if (nbP3d != 0) LineTool::Value(Line, i-1, tabP);
845 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabPP, tabPP2d);
846 else if (nbP2d != 0) LineTool::Value(Line, i, tabPP2d);
847 else if (nbP3d != 0) LineTool::Value(Line, i, tabPP);
849 for (j = 1; j <= nbP3d; j++) {
852 dist += P2.Distance(P1);
854 for (j = 1; j <= nbP2d; j++) {
857 dist += P22d.Distance(P12d);
859 if(Par == Approx_ChordLength)
860 TheParameters(i) = TheParameters(i-1) + dist;
861 else {// Par == Approx_Centripetal
862 TheParameters(i) = TheParameters(i-1) + Sqrt(dist);
865 for (i = firstP; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP);
868 for (i = firstP; i <= lastP; i++) {
869 TheParameters(i) = (Standard_Real(i)-firstP)/
870 (Standard_Real(lastP)-Standard_Real(firstP));
876 Standard_Boolean Approx_ComputeLine::Compute(const MultiLine& Line,
877 const Standard_Integer fpt,
878 const Standard_Integer lpt,
880 Standard_Real& TheTol3d,
881 Standard_Real& TheTol2d)
884 Standard_Integer deg, i;
885 Standard_Boolean mydone;
887 Standard_Integer nbp = lpt-fpt+1;
889 math_Vector ParSav(Para.Lower(), Para.Upper());
890 for (i = Para.Lower(); i <= Para.Upper(); i++) {
893 Standard_Integer Mdegmax = mydegremax;
894 if(nbp < Mdegmax+5 && mycut) {
897 if(Mdegmax < mydegremin) {
898 Mdegmax = mydegremin;
901 currenttol3d = currenttol2d = RealLast();
902 for (deg = Min(nbp-1,mydegremin); deg <= Mdegmax; deg++) {
903 AppParCurves_MultiCurve mySCU(deg+1);
905 Approx_ParLeastSquareOfMyGradient SQ(Line, fpt, lpt,
906 myfirstC, mylastC, Para, deg+1);
907 mydone = SQ.IsDone();
908 mySCU = SQ.BezierValue();
909 SQ.Error(Fv, TheTol3d, TheTol2d);
912 Approx_MyGradient GRAD(Line, fpt, lpt, myConstraints,
913 Para, deg, mytol3d, mytol2d, myitermax);
914 mydone = GRAD.IsDone();
915 mySCU = GRAD.Value();
916 if (mySCU.NbCurves() == 0)
918 TheTol3d = GRAD.MaxError3d();
919 TheTol2d = GRAD.MaxError2d();
921 Standard_Real uu1 = Para(Para.Lower()), uu2;
922 Standard_Boolean restau = Standard_False;
923 for ( i = Para.Lower()+1; i <= Para.Upper(); i++) {
926 restau = Standard_True;
927 // cout << "restau = Standard_True" << endl;
933 for (i = Para.Lower(); i <= Para.Upper(); i++) {
938 if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
939 // Stockage de la multicurve approximee.
940 tolreached = Standard_True;
942 if (mydebug) DUMP(mySCU);
944 myMultiCurves.Append(mySCU);
945 // Stockage des parametres de la partie de MultiLine approximee:
946 // A ameliorer !! (bq trop de recopies)
947 Handle(TColStd_HArray1OfReal) ThePar =
948 new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
949 for (i = Para.Lower(); i <= Para.Upper(); i++) {
950 ThePar->SetValue(i, Para(i));
952 myPar.Append(ThePar);
953 Tolers3d.Append(TheTol3d);
954 Tolers2d.Append(TheTol2d);
955 return Standard_True;
959 if (TheTol3d <= currenttol3d && TheTol2d <= currenttol2d) {
960 TheMultiCurve = mySCU;
961 currenttol3d = TheTol3d;
962 currenttol2d = TheTol2d;
963 myParameters = new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
964 for (i = Para.Lower(); i <= Para.Upper(); i++) {
965 myParameters->SetValue(i, Para(i));
971 return Standard_False;
977 Standard_Boolean Approx_ComputeLine::ComputeCurve(const MultiLine& Line,
978 const Standard_Integer firstpt,
979 const Standard_Integer lastpt)
981 Standard_Integer i, j, nbP3d, nbP2d, deg;
986 Standard_Boolean Tangent1, Tangent2, Parallel, mydone= Standard_False;
987 Standard_Integer myfirstpt = firstpt, mylastpt = lastpt;
988 Standard_Integer nbp = lastpt-firstpt+1, Kopt = 0;
989 AppParCurves_Constraint FirstC, LastC;
990 FirstC = AppParCurves_PassPoint;
991 LastC = AppParCurves_PassPoint;
992 math_Vector Para(firstpt, lastpt);
994 Parameters(Line, firstpt, lastpt, Para);
996 nbP3d = LineTool::NbP3d(Line);
997 nbP2d = LineTool::NbP2d(Line);
998 Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
999 if (nbP3d == 0) mynbP3d = 1 ;
1000 if (nbP2d == 0) mynbP2d = 1 ;
1003 TColgp_Array1OfVec tabV1(1, mynbP3d), tabV2(1, mynbP3d);
1004 TColgp_Array1OfPnt tabP1(1, mynbP3d), tabP2(1, mynbP3d), tabP(1, mynbP3d);
1005 TColgp_Array1OfVec2d tabV12d(1, mynbP2d), tabV22d(1, mynbP2d);
1006 TColgp_Array1OfPnt2d tabP12d(1, mynbP2d), tabP22d(1, mynbP2d), tabP2d(1, mynbP2d);
1008 if (nbP3d != 0 && nbP2d != 0) {
1009 LineTool::Value(Line, myfirstpt,tabP1,tabP12d);
1010 LineTool::Value(Line, mylastpt,tabP2,tabP22d);
1011 Tangent1 = LineTool::Tangency(Line, myfirstpt,tabV1,tabV12d);
1012 Tangent2 = LineTool::Tangency(Line, mylastpt,tabV2,tabV22d);
1014 else if (nbP2d != 0) {
1015 LineTool::Value(Line, myfirstpt,tabP12d);
1016 LineTool::Value(Line, mylastpt,tabP22d);
1017 Tangent1 = LineTool::Tangency(Line, myfirstpt, tabV12d);
1018 Tangent2 = LineTool::Tangency(Line, mylastpt, tabV22d);
1021 LineTool::Value(Line, myfirstpt,tabP1);
1022 LineTool::Value(Line, mylastpt,tabP2);
1023 Tangent1 = LineTool::Tangency(Line, myfirstpt, tabV1);
1024 Tangent2 = LineTool::Tangency(Line, mylastpt, tabV2);
1027 if (Tangent1) Kopt++;
1028 if (Tangent2) Kopt++;
1032 // S il n y a que 2 points, on verifie quand meme que les tangentes sont
1034 Parallel = Standard_True;
1036 for (i = 1; i <= nbP3d; i++) {
1037 gp_Vec PVec(tabP1(i), tabP2(i));
1039 if (!PVec.IsParallel(V13d, Precision::Angular())) {
1040 Parallel = Standard_False;
1044 for (i = 1; i <= nbP2d; i++) {
1045 gp_Vec2d PVec2d(tabP12d(i), tabP22d(i));
1047 if (!PVec2d.IsParallel(V12d, Precision::Angular())) {
1048 Parallel = Standard_False;
1055 for (i = 1; i <= nbP3d; i++) {
1056 gp_Vec PVec(tabP1(i), tabP2(i));
1058 if (!PVec.IsParallel(V23d, Precision::Angular())) {
1059 Parallel = Standard_False;
1063 for (i = 1; i <= nbP2d; i++) {
1064 gp_Vec2d PVec2d(tabP12d(i), tabP22d(i));
1066 if (!PVec2d.IsParallel(V22d, Precision::Angular())) {
1067 Parallel = Standard_False;
1075 if (mydebug) cout <<"droite mais tangentes pas vraiment paralleles!!"<< endl;
1078 AppParCurves_MultiCurve mySCU(mydegremin+1);
1079 if (nbP3d != 0 && nbP2d != 0) {
1080 AppParCurves_MultiPoint MPole1(tabP1, tabP12d);
1081 AppParCurves_MultiPoint MPole2(tabP2, tabP22d);
1082 mySCU.SetValue(1, MPole1);
1083 mySCU.SetValue(mydegremin+1, MPole2);
1084 for (i = 2; i <= mydegremin; i++) {
1085 for (j = 1; j<= nbP3d; j++) {
1088 tabP(j).SetXYZ(P1.XYZ()+(i-1)*(P2.XYZ()-P1.XYZ())/mydegremin);
1090 for (j = 1; j<= nbP2d; j++) {
1093 tabP2d(j).SetXY(P12d.XY()+(i-1)*(P22d.XY()-P12d.XY())/mydegremin);
1095 AppParCurves_MultiPoint MPole(tabP, tabP2d);
1096 mySCU.SetValue(i, MPole);
1100 else if (nbP3d != 0) {
1101 AppParCurves_MultiPoint MPole1(tabP1);
1102 AppParCurves_MultiPoint MPole2(tabP2);
1103 mySCU.SetValue(1, MPole1);
1104 mySCU.SetValue(mydegremin+1, MPole2);
1105 for (i = 2; i <= mydegremin; i++) {
1106 for (j = 1; j<= nbP3d; j++) {
1109 tabP(j).SetXYZ(P1.XYZ()+(i-1)*(P2.XYZ()-P1.XYZ())/mydegremin);
1111 AppParCurves_MultiPoint MPole(tabP);
1112 mySCU.SetValue(i, MPole);
1115 else if (nbP2d != 0) {
1116 AppParCurves_MultiPoint MPole1(tabP12d);
1117 AppParCurves_MultiPoint MPole2(tabP22d);
1118 mySCU.SetValue(1, MPole1);
1119 mySCU.SetValue(mydegremin+1, MPole2);
1120 for (i = 2; i <= mydegremin; i++) {
1121 for (j = 1; j<= nbP2d; j++) {
1124 tabP2d(j).SetXY(P12d.XY()+(i-1)*(P22d.XY()-P12d.XY())/mydegremin);
1126 AppParCurves_MultiPoint MPole(tabP2d);
1127 mySCU.SetValue(i, MPole);
1130 mydone = Standard_True;
1131 // Stockage de la multicurve approximee.
1132 tolreached = Standard_True;
1134 if (mydebug) DUMP(mySCU);
1136 myMultiCurves.Append(mySCU);
1137 Handle(TColStd_HArray1OfReal) ThePar = new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1138 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1139 ThePar->SetValue(i, Para(i));
1141 myPar.Append(ThePar);
1142 Tolers3d.Append(Precision::Confusion());
1143 Tolers2d.Append(Precision::PConfusion());
1147 // avec les tangentes.
1149 AppParCurves_MultiCurve mySCU(deg+1);
1150 AppParCurves_Constraint Cons = AppParCurves_TangencyPoint;
1151 Standard_Real lambda1, lambda2;
1152 math_Vector V1(1, nbP3d*3+nbP2d*2);
1153 math_Vector V2(1, nbP3d*3+nbP2d*2);
1154 FirstTangencyVector(Line, myfirstpt, V1);
1155 lambda1 = SearchFirstLambda(Line, Para, V1, myfirstpt);
1157 LastTangencyVector(Line, mylastpt, V2);
1158 lambda2 = SearchLastLambda(Line, Para, V2, mylastpt);
1160 Approx_ParLeastSquareOfMyGradient
1161 LSQ(Line, myfirstpt, mylastpt,
1162 Cons, Cons, Para, deg+1);
1164 lambda1 = lambda1/deg;
1165 lambda2 = lambda2/deg;
1166 LSQ.Perform(Para, V1, V2, lambda1, lambda2);
1167 mydone = LSQ.IsDone();
1168 mySCU = LSQ.BezierValue();
1171 Standard_Real Fv, TheTol3d, TheTol2d;
1172 LSQ.Error(Fv, TheTol3d, TheTol2d);
1174 // Stockage de la multicurve approximee.
1175 tolreached = Standard_True;
1177 if (mydebug) DUMP(mySCU);
1179 myMultiCurves.Append(mySCU);
1180 Handle(TColStd_HArray1OfReal) ThePar =
1181 new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1182 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1183 ThePar->SetValue(i, Para(i));
1185 myPar.Append(ThePar);
1186 Tolers3d.Append(TheTol3d);
1187 Tolers2d.Append(TheTol2d);
1188 return Standard_True;
1195 void Approx_ComputeLine::Init(const Standard_Integer degreemin,
1196 const Standard_Integer degreemax,
1197 const Standard_Real Tolerance3d,
1198 const Standard_Real Tolerance2d,
1199 const Standard_Integer NbIterations,
1200 const Standard_Boolean cutting,
1201 const Approx_ParametrizationType parametrization,
1202 const Standard_Boolean Squares)
1204 mydegremin = degreemin;
1205 mydegremax = degreemax;
1206 mytol3d = Tolerance3d;
1207 mytol2d = Tolerance2d;
1208 Par = parametrization;
1209 mysquares = Squares;
1211 myitermax = NbIterations;
1216 void Approx_ComputeLine::SetDegrees(const Standard_Integer degreemin,
1217 const Standard_Integer degreemax)
1219 mydegremin = degreemin;
1220 mydegremax = degreemax;
1224 void Approx_ComputeLine::SetTolerances(const Standard_Real Tolerance3d,
1225 const Standard_Real Tolerance2d)
1227 mytol3d = Tolerance3d;
1228 mytol2d = Tolerance2d;
1232 void Approx_ComputeLine::SetConstraints(const AppParCurves_Constraint FirstC,
1233 const AppParCurves_Constraint LastC)
1241 Standard_Boolean Approx_ComputeLine::IsAllApproximated()
1246 Standard_Boolean Approx_ComputeLine::IsToleranceReached()
1251 void Approx_ComputeLine::Error(const Standard_Integer Index,
1252 Standard_Real& tol3d,
1253 Standard_Real& tol2d) const
1255 tol3d = Tolers3d.Value(Index);
1256 tol2d = Tolers2d.Value(Index);
1259 void Approx_ComputeLine::Parametrization(Approx_ParametrizationType& partype) const