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();
79 Handle(Geom_BezierCurve) BSp;
80 Handle(Geom2d_BezierCurve) BSp2d;
82 TColgp_Array1OfPnt tabPoles(1, nbpoles);
83 TColgp_Array1OfPnt2d tabPoles2d(1, nbpoles);
87 for (i = 1; i <= C.NbCurves(); i++) {
88 if (C.Dimension(i) == 3) {
90 BSp = new Geom_BezierCurve(tabPoles);
91 sprintf(solname, "%s%i%s_%i", "c", i, "3d", nbappel);
94 DrawTrSurf::Set(Temp, BSp);
95 // DrawTrSurf::Set(solname, BSp);
99 C.Curve(i, tabPoles2d);
100 BSp2d = new Geom2d_BezierCurve(tabPoles2d);
101 sprintf(solname, "%s%i%s_%i", "c", i, "2d", nbappel);
103 char* Temp = solname;
104 DrawTrSurf::Set(Temp, BSp2d);
105 // DrawTrSurf::Set(solname, BSp2d);
117 void Approx_ComputeLine::FirstTangencyVector(const MultiLine& Line,
118 const Standard_Integer index,
119 math_Vector& V) const
122 Standard_Integer i, j, nbP2d, nbP3d;
123 nbP3d = LineTool::NbP3d(Line);
124 nbP2d = LineTool::NbP2d(Line);
125 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
126 if (nbP3d == 0) mynbP3d = 1;
127 if (nbP2d == 0) mynbP2d = 1;
128 Standard_Boolean Ok=Standard_False;
129 TColgp_Array1OfVec TabV(1, mynbP3d);
130 TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
132 if (nbP3d != 0 && nbP2d != 0)
133 Ok = LineTool::Tangency(Line, index, TabV, TabV2d);
135 Ok = LineTool::Tangency(Line, index, TabV2d);
137 Ok = LineTool::Tangency(Line, index, TabV);
142 for (i = TabV.Lower(); i <= TabV.Upper(); i++) {
144 V(j+1) = TabV(i).Y();
145 V(j+2) = TabV(i).Z();
151 for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) {
152 V(j) = TabV2d(i).X();
153 V(j+1) = TabV2d(i).Y();
160 // recherche d un vecteur tangent par construction d une parabole:
161 AppParCurves_Constraint firstC, lastC;
162 firstC = lastC = AppParCurves_PassPoint;
163 Standard_Integer nbpoles = 3;
164 math_Vector mypar(index, index+2);
165 Parameters(Line, index, index+2, mypar);
166 Approx_ParLeastSquareOfMyGradient
167 LSQ(Line, index, index+2, firstC, lastC, mypar, nbpoles);
168 AppParCurves_MultiCurve C = LSQ.BezierValue();
175 for (i = 1; i <= nbP3d; i++) {
176 C.D1(i, 0.0, myP, myV);
183 for (i = nbP3d+1; i <= nbP3d+nbP2d; i++) {
184 C.D1(i, 0.0, myP2d, myV2d);
193 void Approx_ComputeLine::LastTangencyVector(const MultiLine& Line,
194 const Standard_Integer index,
195 math_Vector& V) const
197 Standard_Integer i, j, nbP2d, nbP3d;
198 nbP3d = LineTool::NbP3d(Line);
199 nbP2d = LineTool::NbP2d(Line);
200 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
201 if (nbP3d == 0) mynbP3d = 1;
202 if (nbP2d == 0) mynbP2d = 1;
203 Standard_Boolean Ok=Standard_False;
204 TColgp_Array1OfVec TabV(1, mynbP3d);
205 TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
208 if (nbP3d != 0 && nbP2d != 0)
209 Ok = LineTool::Tangency(Line, index, TabV, TabV2d);
211 Ok = LineTool::Tangency(Line, index, TabV2d);
213 Ok = LineTool::Tangency(Line, index, TabV);
218 for (i = TabV.Lower(); i <= TabV.Upper(); i++) {
220 V(j+1) = TabV(i).Y();
221 V(j+2) = TabV(i).Z();
227 for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) {
228 V(j) = TabV2d(i).X();
229 V(j+1) = TabV2d(i).Y();
236 // recherche d un vecteur tangent par construction d une parabole:
237 AppParCurves_Constraint firstC, lastC;
238 firstC = lastC = AppParCurves_PassPoint;
239 Standard_Integer nbpoles = 3;
240 math_Vector mypar(index-2, index);
241 Parameters(Line, index-2, index, mypar);
242 Approx_ParLeastSquareOfMyGradient
243 LSQ(Line, index-2, index, firstC, lastC, mypar, nbpoles);
244 AppParCurves_MultiCurve C = LSQ.BezierValue();
251 for (i = 1; i <= nbP3d; i++) {
252 C.D1(i, 1.0, myP, myV);
259 for (i = nbP3d+1; i <= nbP3d+nbP2d; i++) {
260 C.D1(i, 1.0, myP2d, myV2d);
271 Standard_Real Approx_ComputeLine::
272 SearchFirstLambda(const MultiLine& Line,
273 const math_Vector& TheParam,
274 const math_Vector& V,
275 const Standard_Integer index) const
278 // dq/dw = lambda* V = (p2-p1)/(u2-u1)
280 Standard_Integer nbP2d, nbP3d;
283 nbP3d = LineTool::NbP3d(Line);
284 nbP2d = LineTool::NbP2d(Line);
285 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
286 if (nbP3d == 0) mynbP3d = 1;
287 if (nbP2d == 0) mynbP2d = 1;
288 TColgp_Array1OfPnt tabP1(1, mynbP3d), tabP2(1, mynbP3d);
289 TColgp_Array1OfPnt2d tabP12d(1, mynbP2d), tabP22d(1, mynbP2d);
292 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP1, tabP12d);
293 else if (nbP2d != 0) LineTool::Value(Line, index, tabP12d);
294 else if (nbP3d != 0) LineTool::Value(Line, index, tabP1);
296 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index+1, tabP2, tabP22d);
297 else if (nbP2d != 0) LineTool::Value(Line, index+1, tabP22d);
298 else if (nbP3d != 0) LineTool::Value(Line, index+1, tabP2);
301 Standard_Real U1 = TheParam(index), U2 = TheParam(index+1);
302 Standard_Real lambda, S;
303 Standard_Integer low = V.Lower();
308 gp_Vec P1P2(P1, P2), myV;
309 myV.SetCoord(V(low), V(low+1), V(low+2));
310 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
311 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
316 gp_Vec2d P1P2(P12d, P22d), myV;
317 myV.SetCoord(V(low), V(low+1));
318 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
319 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
326 Standard_Real Approx_ComputeLine::
327 SearchLastLambda(const MultiLine& Line,
328 const math_Vector& TheParam,
329 const math_Vector& V,
330 const Standard_Integer index) const
332 // dq/dw = lambda* V = (p2-p1)/(u2-u1)
334 Standard_Integer nbP2d, nbP3d;
337 nbP3d = LineTool::NbP3d(Line);
338 nbP2d = LineTool::NbP2d(Line);
339 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
340 if (nbP3d == 0) mynbP3d = 1;
341 if (nbP2d == 0) mynbP2d = 1;
342 TColgp_Array1OfPnt tabP(1, mynbP3d), tabP2(1, mynbP3d);
343 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d), tabP22d(1, mynbP2d);
345 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index-1, tabP, tabP2d);
346 else if (nbP2d != 0) LineTool::Value(Line, index-1, tabP2d);
347 else if (nbP3d != 0) LineTool::Value(Line, index-1, tabP);
349 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP2, tabP22d);
350 else if (nbP2d != 0) LineTool::Value(Line, index, tabP22d);
351 else if (nbP3d != 0) LineTool::Value(Line, index, tabP2);
354 Standard_Real U1 = TheParam(index-1), U2 = TheParam(index);
355 Standard_Real lambda, S;
356 Standard_Integer low = V.Lower();
361 gp_Vec P1P2(P1, P2), myV;
362 myV.SetCoord(V(low), V(low+1), V(low+2));
363 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
364 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
369 gp_Vec2d P1P2(P12d, P22d), myV;
370 myV.SetCoord(V(low), V(low+1));
371 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
372 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
380 Approx_ComputeLine::Approx_ComputeLine
381 (const MultiLine& Line,
382 const math_Vector& Parameters,
383 const Standard_Integer degreemin,
384 const Standard_Integer degreemax,
385 const Standard_Real Tolerance3d,
386 const Standard_Real Tolerance2d,
387 const Standard_Integer NbIterations,
388 const Standard_Boolean cutting,
389 const Standard_Boolean Squares)
391 myIsClear (Standard_False)
393 myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(),
395 for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) {
396 myfirstParam->SetValue(i, Parameters(i));
398 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
399 Par = Approx_IsoParametric;
400 mydegremin = degreemin;
401 mydegremax = degreemax;
402 mytol3d = Tolerance3d;
403 mytol2d = Tolerance2d;
406 myitermax = NbIterations;
407 alldone = Standard_False;
408 myfirstC = AppParCurves_TangencyPoint;
409 mylastC = AppParCurves_TangencyPoint;
414 Approx_ComputeLine::Approx_ComputeLine
415 (const math_Vector& Parameters,
416 const Standard_Integer degreemin,
417 const Standard_Integer degreemax,
418 const Standard_Real Tolerance3d,
419 const Standard_Real Tolerance2d,
420 const Standard_Integer NbIterations,
421 const Standard_Boolean cutting,
422 const Standard_Boolean Squares)
424 myIsClear (Standard_False)
426 myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(),
428 for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) {
429 myfirstParam->SetValue(i, Parameters(i));
431 myfirstC = AppParCurves_TangencyPoint;
432 mylastC = AppParCurves_TangencyPoint;
433 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
434 Par = Approx_IsoParametric;
435 mydegremin = degreemin;
436 mydegremax = degreemax;
437 mytol3d = Tolerance3d;
438 mytol2d = Tolerance2d;
441 myitermax = NbIterations;
442 alldone = Standard_False;
445 Approx_ComputeLine::Approx_ComputeLine
446 (const Standard_Integer degreemin,
447 const Standard_Integer degreemax,
448 const Standard_Real Tolerance3d,
449 const Standard_Real Tolerance2d,
450 const Standard_Integer NbIterations,
451 const Standard_Boolean cutting,
452 const Approx_ParametrizationType parametrization,
453 const Standard_Boolean Squares)
455 myIsClear (Standard_False)
457 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
458 Par = parametrization;
459 mydegremin = degreemin;
460 mydegremax = degreemax;
461 mytol3d = Tolerance3d;
462 mytol2d = Tolerance2d;
465 myitermax = NbIterations;
466 myfirstC = AppParCurves_TangencyPoint;
467 mylastC = AppParCurves_TangencyPoint;
468 alldone = Standard_False;
472 Approx_ComputeLine::Approx_ComputeLine
473 (const MultiLine& Line,
474 const Standard_Integer degreemin,
475 const Standard_Integer degreemax,
476 const Standard_Real Tolerance3d,
477 const Standard_Real Tolerance2d,
478 const Standard_Integer NbIterations,
479 const Standard_Boolean cutting,
480 const Approx_ParametrizationType parametrization,
481 const Standard_Boolean Squares)
483 myIsClear (Standard_False)
485 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
486 alldone = Standard_False;
487 mydegremin = degreemin;
488 mydegremax = degreemax;
489 mytol3d = Tolerance3d;
490 mytol2d = Tolerance2d;
493 myitermax = NbIterations;
494 Par = parametrization;
495 myfirstC = AppParCurves_TangencyPoint;
496 mylastC = AppParCurves_TangencyPoint;
503 void Approx_ComputeLine::Perform(const MultiLine& Line)
506 if (mydebug) DUMP(Line);
510 myMultiCurves.Clear();
516 else myIsClear = Standard_False;
518 Standard_Integer i, nbp, Thefirstpt, Thelastpt, oldlastpt;
519 Standard_Boolean Finish = Standard_False,
520 begin = Standard_True, Ok = Standard_False,
521 GoUp = Standard_False, Interpol;
522 Standard_Real thetol3d, thetol2d;
523 Approx_Status MyStatus;
524 // gp_Vec V13d, V23d;
526 Thefirstpt = LineTool::FirstPoint(Line);
527 Thelastpt = LineTool::LastPoint(Line);
528 Standard_Integer myfirstpt = Thefirstpt;
529 Standard_Integer mylastpt = Thelastpt;
531 AppParCurves_ConstraintCouple myCouple1(myfirstpt, myfirstC);
532 AppParCurves_ConstraintCouple myCouple2(mylastpt, mylastC);
533 myConstraints->SetValue(1, myCouple1);
534 myConstraints->SetValue(2, myCouple2);
536 math_Vector TheParam(Thefirstpt, Thelastpt);
540 if(myfirstParam.IsNull()) {
541 Parameters(Line, Thefirstpt, Thelastpt, TheParam);
544 for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) {
545 TheParam(i+Thefirstpt-1) = myfirstParam->Value(i);
548 TheMultiCurve = AppParCurves_MultiCurve();
549 alldone = Compute(Line, myfirstpt, mylastpt, TheParam, thetol3d, thetol2d);
550 if(!alldone && TheMultiCurve.NbCurves() > 0) {
552 if (mydebug) DUMP(TheMultiCurve);
554 myMultiCurves.Append(TheMultiCurve);
555 Tolers3d.Append(currenttol3d);
556 Tolers2d.Append(currenttol2d);
557 Handle(TColStd_HArray1OfReal) ThePar = new TColStd_HArray1OfReal(myfirstpt, mylastpt);
558 for (i = myfirstpt; i <= mylastpt; i++) {
559 ThePar->SetValue(i, myParameters->Value(i));
561 myPar.Append(ThePar);
566 oldlastpt = mylastpt;
567 // Gestion du decoupage de la multiline pour approximer:
571 // Calcul de la partie a approximer.
572 myfirstpt = mylastpt;
573 mylastpt = Thelastpt;
574 if (myfirstpt == Thelastpt) {
575 Finish = Standard_True;
576 alldone = Standard_True;
581 nbp = mylastpt - myfirstpt + 1;
582 MyStatus = LineTool::WhatStatus(Line, myfirstpt, mylastpt);
583 if (MyStatus == Approx_NoPointsAdded && nbp <= mydegremax+1) {
584 Interpol = ComputeCurve(Line, myfirstpt, mylastpt);
586 if (mylastpt == Thelastpt) {
587 Finish = Standard_True;
588 alldone = Standard_True;
593 mylastpt = Standard_Integer((myfirstpt + mylastpt)/2);
596 GoUp = Standard_False;
599 // Verification du nombre de points restants par rapport au degre
601 // ==============================================================
602 nbp = mylastpt - myfirstpt + 1;
603 MyStatus = LineTool::WhatStatus(Line, myfirstpt, mylastpt);
604 if (nbp <= mydegremax+5 ) {
605 // Rajout necessaire de points si possible.
606 // ========================================
607 GoUp = Standard_False;
609 Standard_Boolean FailOnPointsAdded = Standard_False;
610 if (MyStatus == Approx_PointsAdded) {
611 // Appel recursif du decoupage:
612 GoUp = Standard_True;
614 MultiLine OtherLine =LineTool::MakeMLBetween(Line, myfirstpt,
617 Standard_Integer nbpdsotherligne = LineTool::FirstPoint(OtherLine)
618 -LineTool::LastPoint(OtherLine);
620 //-- Si MakeML a echoue on retourne une ligne vide
621 if ((nbpdsotherligne == 0) || myMultiLineNb >= 3)
623 FailOnPointsAdded = Standard_True;
624 //-- cout<<" ** ApproxComputeLine MakeML Echec ** LBR lbr "<<endl;
625 if (myfirstpt == mylastpt) break; // Pour etre sur de ne pas
626 // planter la station !!
627 myCouple1.SetIndex(myfirstpt);
628 myCouple2.SetIndex(mylastpt);
629 myConstraints->SetValue(1, myCouple1);
630 myConstraints->SetValue(2, myCouple2);
632 math_Vector Param(myfirstpt, mylastpt);
633 Approx_ParametrizationType SavePar = Par;
634 Par = Approx_IsoParametric;
635 Parameters(Line, myfirstpt, mylastpt, Param);
636 TheMultiCurve = AppParCurves_MultiCurve();
637 Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d);
640 Standard_Real tt3d = currenttol3d, tt2d = currenttol2d;
641 Handle(TColStd_HArray1OfReal) saveParameters = myParameters;
642 AppParCurves_MultiCurve saveMultiCurve = TheMultiCurve;
644 if(SavePar != Approx_IsoParametric)
647 Par = Approx_ChordLength;
649 Parameters(Line, myfirstpt, mylastpt, Param);
650 Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d);
652 if (!Ok && tt3d <= currenttol3d && tt2d <= currenttol2d) {
653 currenttol3d = tt3d; currenttol2d = tt2d;
654 myParameters = saveParameters;
655 TheMultiCurve = saveMultiCurve;
660 oldlastpt = mylastpt;
662 tolreached = Standard_False;
663 if (TheMultiCurve.NbCurves() == 0) {
664 myMultiCurves.Clear();
668 if (mydebug) DUMP(TheMultiCurve);
670 myMultiCurves.Append(TheMultiCurve);
671 Tolers3d.Append(currenttol3d);
672 Tolers2d.Append(currenttol2d);
674 Handle(TColStd_HArray1OfReal) ThePar = new TColStd_HArray1OfReal(myfirstpt, oldlastpt);
675 for (i = myfirstpt; i <= oldlastpt; i++) {
676 ThePar->SetValue(i, myParameters->Value(i));
678 myPar.Append(ThePar);
680 myfirstpt = oldlastpt;
681 mylastpt = Thelastpt;
686 myIsClear = Standard_True;
689 myfirstpt = mylastpt;
690 mylastpt = Thelastpt;
694 if (MyStatus == Approx_NoPointsAdded && !begin) {
695 // On rend la meilleure approximation obtenue precedemment.
696 // ========================================================
697 GoUp = Standard_True;
698 tolreached = Standard_False;
699 if (TheMultiCurve.NbCurves() == 0) {
700 myMultiCurves.Clear();
704 if (mydebug) DUMP(TheMultiCurve);
706 myMultiCurves.Append(TheMultiCurve);
707 Tolers3d.Append(currenttol3d);
708 Tolers2d.Append(currenttol2d);
710 Handle(TColStd_HArray1OfReal) ThePar = new TColStd_HArray1OfReal(myfirstpt, oldlastpt);
711 for (i = myfirstpt; i <= oldlastpt; i++) {
712 ThePar->SetValue(i, myParameters->Value(i));
714 myPar.Append(ThePar);
716 myfirstpt = oldlastpt;
717 mylastpt = Thelastpt;
720 else if (MyStatus == Approx_NoApproximation) {
721 // On ne fait pas d approximation entre myfirstpt et mylastpt.
722 // ===========================================================
723 // On stocke pour pouvoir en informer l utilisateur.
724 GoUp = Standard_True;
725 myfirstpt = mylastpt;
726 mylastpt = Thelastpt;
730 if (myfirstpt == Thelastpt) {
731 Finish = Standard_True;
732 alldone = Standard_True;
736 if (myfirstpt == mylastpt) break; // Pour etre sur de ne pas
737 // planter la station !!
738 myCouple1.SetIndex(myfirstpt);
739 myCouple2.SetIndex(mylastpt);
740 myConstraints->SetValue(1, myCouple1);
741 myConstraints->SetValue(2, myCouple2);
743 // Calcul des parametres sur ce nouvel intervalle.
744 // On recupere les parametres initiaux lors du decoupage.
746 math_Vector Param(myfirstpt, mylastpt);
748 if(myfirstParam.IsNull()) {
749 Parameters(Line, myfirstpt, mylastpt, Param);
752 for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) {
753 Param(i) = myfirstParam->Value(i);
755 myfirstParam.Nullify();
758 begin = Standard_False;
761 Standard_Real pfirst = TheParam.Value(myfirstpt);
762 Standard_Real plast = TheParam.Value(mylastpt);
763 for (i = myfirstpt; i <= mylastpt; i++) {
764 Param(i) = (TheParam.Value(i)-pfirst)/(plast-pfirst);
768 TheMultiCurve = AppParCurves_MultiCurve();
769 Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d);
778 const TColStd_Array1OfReal& Approx_ComputeLine::Parameters(const Standard_Integer Index) const
780 return (myPar.Value(Index))->Array1();
784 Standard_Integer Approx_ComputeLine::NbMultiCurves()const
786 return myMultiCurves.Length();
789 AppParCurves_MultiCurve& Approx_ComputeLine::ChangeValue(const Standard_Integer Index)
791 return myMultiCurves.ChangeValue(Index);
795 const AppParCurves_MultiCurve& Approx_ComputeLine::Value(const Standard_Integer Index)
798 return myMultiCurves.Value(Index);
802 const AppParCurves_MultiBSpCurve& Approx_ComputeLine::SplineValue()
804 Approx_MCurvesToBSpCurve Trans;
805 Trans.Perform(myMultiCurves);
806 myspline = Trans.Value();
814 void Approx_ComputeLine::Parameters(const MultiLine& Line,
815 const Standard_Integer firstP,
816 const Standard_Integer lastP,
817 math_Vector& TheParameters) const
819 Standard_Integer i, j, Nbp, nbP2d, nbP3d;
823 Nbp = lastP-firstP+1;
825 if (Par == Approx_ChordLength || Par == Approx_Centripetal) {
826 nbP3d = LineTool::NbP3d(Line);
827 nbP2d = LineTool::NbP2d(Line);
828 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
829 if (nbP3d == 0) mynbP3d = 1;
830 if (nbP2d == 0) mynbP2d = 1;
832 TheParameters(firstP) = 0.0;
834 TColgp_Array1OfPnt tabP(1, mynbP3d);
835 TColgp_Array1OfPnt tabPP(1, mynbP3d);
836 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
837 TColgp_Array1OfPnt2d tabPP2d(1, mynbP2d);
839 for (i = firstP+1; i <= lastP; i++) {
840 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i-1, tabP, tabP2d);
841 else if (nbP2d != 0) LineTool::Value(Line, i-1, tabP2d);
842 else if (nbP3d != 0) LineTool::Value(Line, i-1, tabP);
844 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabPP, tabPP2d);
845 else if (nbP2d != 0) LineTool::Value(Line, i, tabPP2d);
846 else if (nbP3d != 0) LineTool::Value(Line, i, tabPP);
848 for (j = 1; j <= nbP3d; j++) {
851 dist += P2.Distance(P1);
853 for (j = 1; j <= nbP2d; j++) {
856 dist += P22d.Distance(P12d);
858 if(Par == Approx_ChordLength)
859 TheParameters(i) = TheParameters(i-1) + dist;
860 else {// Par == Approx_Centripetal
861 TheParameters(i) = TheParameters(i-1) + Sqrt(dist);
864 for (i = firstP; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP);
867 for (i = firstP; i <= lastP; i++) {
868 TheParameters(i) = (Standard_Real(i)-firstP)/
869 (Standard_Real(lastP)-Standard_Real(firstP));
875 Standard_Boolean Approx_ComputeLine::Compute(const MultiLine& Line,
876 const Standard_Integer fpt,
877 const Standard_Integer lpt,
879 Standard_Real& TheTol3d,
880 Standard_Real& TheTol2d)
883 Standard_Integer deg, i;
884 Standard_Boolean mydone;
886 Standard_Integer nbp = lpt-fpt+1;
888 math_Vector ParSav(Para.Lower(), Para.Upper());
889 for (i = Para.Lower(); i <= Para.Upper(); i++) {
892 Standard_Integer Mdegmax = mydegremax;
893 if(nbp < Mdegmax+5 && mycut) {
896 if(Mdegmax < mydegremin) {
897 Mdegmax = mydegremin;
900 currenttol3d = currenttol2d = RealLast();
901 for (deg = Min(nbp-1,mydegremin); deg <= Mdegmax; deg++) {
902 AppParCurves_MultiCurve mySCU(deg+1);
904 Approx_ParLeastSquareOfMyGradient SQ(Line, fpt, lpt,
905 myfirstC, mylastC, Para, deg+1);
906 mydone = SQ.IsDone();
907 mySCU = SQ.BezierValue();
908 SQ.Error(Fv, TheTol3d, TheTol2d);
911 Approx_MyGradient GRAD(Line, fpt, lpt, myConstraints,
912 Para, deg, mytol3d, mytol2d, myitermax);
913 mydone = GRAD.IsDone();
914 mySCU = GRAD.Value();
915 if (mySCU.NbCurves() == 0)
917 TheTol3d = GRAD.MaxError3d();
918 TheTol2d = GRAD.MaxError2d();
920 Standard_Real uu1 = Para(Para.Lower()), uu2;
921 Standard_Boolean restau = Standard_False;
922 for ( i = Para.Lower()+1; i <= Para.Upper(); i++) {
925 restau = Standard_True;
926 // cout << "restau = Standard_True" << endl;
932 for (i = Para.Lower(); i <= Para.Upper(); i++) {
937 if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
938 // Stockage de la multicurve approximee.
939 tolreached = Standard_True;
941 if (mydebug) DUMP(mySCU);
943 myMultiCurves.Append(mySCU);
944 // Stockage des parametres de la partie de MultiLine approximee:
945 // A ameliorer !! (bq trop de recopies)
946 Handle(TColStd_HArray1OfReal) ThePar =
947 new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
948 for (i = Para.Lower(); i <= Para.Upper(); i++) {
949 ThePar->SetValue(i, Para(i));
951 myPar.Append(ThePar);
952 Tolers3d.Append(TheTol3d);
953 Tolers2d.Append(TheTol2d);
954 return Standard_True;
958 if (TheTol3d <= currenttol3d && TheTol2d <= currenttol2d) {
959 TheMultiCurve = mySCU;
960 currenttol3d = TheTol3d;
961 currenttol2d = TheTol2d;
962 myParameters = new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
963 for (i = Para.Lower(); i <= Para.Upper(); i++) {
964 myParameters->SetValue(i, Para(i));
970 return Standard_False;
976 Standard_Boolean Approx_ComputeLine::ComputeCurve(const MultiLine& Line,
977 const Standard_Integer firstpt,
978 const Standard_Integer lastpt)
980 Standard_Integer i, j, nbP3d, nbP2d, deg;
985 Standard_Boolean Tangent1, Tangent2, Parallel, mydone= Standard_False;
986 Standard_Integer myfirstpt = firstpt, mylastpt = lastpt;
987 Standard_Integer nbp = lastpt-firstpt+1, Kopt = 0;
988 AppParCurves_Constraint FirstC, LastC;
989 FirstC = AppParCurves_PassPoint;
990 LastC = AppParCurves_PassPoint;
991 math_Vector Para(firstpt, lastpt);
993 Parameters(Line, firstpt, lastpt, Para);
995 nbP3d = LineTool::NbP3d(Line);
996 nbP2d = LineTool::NbP2d(Line);
997 Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
998 if (nbP3d == 0) mynbP3d = 1 ;
999 if (nbP2d == 0) mynbP2d = 1 ;
1002 TColgp_Array1OfVec tabV1(1, mynbP3d), tabV2(1, mynbP3d);
1003 TColgp_Array1OfPnt tabP1(1, mynbP3d), tabP2(1, mynbP3d), tabP(1, mynbP3d);
1004 TColgp_Array1OfVec2d tabV12d(1, mynbP2d), tabV22d(1, mynbP2d);
1005 TColgp_Array1OfPnt2d tabP12d(1, mynbP2d), tabP22d(1, mynbP2d), tabP2d(1, mynbP2d);
1007 if (nbP3d != 0 && nbP2d != 0) {
1008 LineTool::Value(Line, myfirstpt,tabP1,tabP12d);
1009 LineTool::Value(Line, mylastpt,tabP2,tabP22d);
1010 Tangent1 = LineTool::Tangency(Line, myfirstpt,tabV1,tabV12d);
1011 Tangent2 = LineTool::Tangency(Line, mylastpt,tabV2,tabV22d);
1013 else if (nbP2d != 0) {
1014 LineTool::Value(Line, myfirstpt,tabP12d);
1015 LineTool::Value(Line, mylastpt,tabP22d);
1016 Tangent1 = LineTool::Tangency(Line, myfirstpt, tabV12d);
1017 Tangent2 = LineTool::Tangency(Line, mylastpt, tabV22d);
1020 LineTool::Value(Line, myfirstpt,tabP1);
1021 LineTool::Value(Line, mylastpt,tabP2);
1022 Tangent1 = LineTool::Tangency(Line, myfirstpt, tabV1);
1023 Tangent2 = LineTool::Tangency(Line, mylastpt, tabV2);
1026 if (Tangent1) Kopt++;
1027 if (Tangent2) Kopt++;
1031 // S il n y a que 2 points, on verifie quand meme que les tangentes sont
1033 Parallel = Standard_True;
1035 for (i = 1; i <= nbP3d; i++) {
1036 gp_Vec PVec(tabP1(i), tabP2(i));
1038 if (!PVec.IsParallel(V13d, Precision::Angular())) {
1039 Parallel = Standard_False;
1043 for (i = 1; i <= nbP2d; i++) {
1044 gp_Vec2d PVec2d(tabP12d(i), tabP22d(i));
1046 if (!PVec2d.IsParallel(V12d, Precision::Angular())) {
1047 Parallel = Standard_False;
1054 for (i = 1; i <= nbP3d; i++) {
1055 gp_Vec PVec(tabP1(i), tabP2(i));
1057 if (!PVec.IsParallel(V23d, Precision::Angular())) {
1058 Parallel = Standard_False;
1062 for (i = 1; i <= nbP2d; i++) {
1063 gp_Vec2d PVec2d(tabP12d(i), tabP22d(i));
1065 if (!PVec2d.IsParallel(V22d, Precision::Angular())) {
1066 Parallel = Standard_False;
1074 if (mydebug) cout <<"droite mais tangentes pas vraiment paralleles!!"<< endl;
1077 AppParCurves_MultiCurve mySCU(mydegremin+1);
1078 if (nbP3d != 0 && nbP2d != 0) {
1079 AppParCurves_MultiPoint MPole1(tabP1, tabP12d);
1080 AppParCurves_MultiPoint MPole2(tabP2, tabP22d);
1081 mySCU.SetValue(1, MPole1);
1082 mySCU.SetValue(mydegremin+1, MPole2);
1083 for (i = 2; i <= mydegremin; i++) {
1084 for (j = 1; j<= nbP3d; j++) {
1087 tabP(j).SetXYZ(P1.XYZ()+(i-1)*(P2.XYZ()-P1.XYZ())/mydegremin);
1089 for (j = 1; j<= nbP2d; j++) {
1092 tabP2d(j).SetXY(P12d.XY()+(i-1)*(P22d.XY()-P12d.XY())/mydegremin);
1094 AppParCurves_MultiPoint MPole(tabP, tabP2d);
1095 mySCU.SetValue(i, MPole);
1099 else if (nbP3d != 0) {
1100 AppParCurves_MultiPoint MPole1(tabP1);
1101 AppParCurves_MultiPoint MPole2(tabP2);
1102 mySCU.SetValue(1, MPole1);
1103 mySCU.SetValue(mydegremin+1, MPole2);
1104 for (i = 2; i <= mydegremin; i++) {
1105 for (j = 1; j<= nbP3d; j++) {
1108 tabP(j).SetXYZ(P1.XYZ()+(i-1)*(P2.XYZ()-P1.XYZ())/mydegremin);
1110 AppParCurves_MultiPoint MPole(tabP);
1111 mySCU.SetValue(i, MPole);
1114 else if (nbP2d != 0) {
1115 AppParCurves_MultiPoint MPole1(tabP12d);
1116 AppParCurves_MultiPoint MPole2(tabP22d);
1117 mySCU.SetValue(1, MPole1);
1118 mySCU.SetValue(mydegremin+1, MPole2);
1119 for (i = 2; i <= mydegremin; i++) {
1120 for (j = 1; j<= nbP2d; j++) {
1123 tabP2d(j).SetXY(P12d.XY()+(i-1)*(P22d.XY()-P12d.XY())/mydegremin);
1125 AppParCurves_MultiPoint MPole(tabP2d);
1126 mySCU.SetValue(i, MPole);
1129 mydone = Standard_True;
1130 // Stockage de la multicurve approximee.
1131 tolreached = Standard_True;
1133 if (mydebug) DUMP(mySCU);
1135 myMultiCurves.Append(mySCU);
1136 Handle(TColStd_HArray1OfReal) ThePar = new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1137 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1138 ThePar->SetValue(i, Para(i));
1140 myPar.Append(ThePar);
1141 Tolers3d.Append(Precision::Confusion());
1142 Tolers2d.Append(Precision::PConfusion());
1146 // avec les tangentes.
1148 AppParCurves_MultiCurve mySCU(deg+1);
1149 AppParCurves_Constraint Cons = AppParCurves_TangencyPoint;
1150 Standard_Real lambda1, lambda2;
1151 math_Vector V1(1, nbP3d*3+nbP2d*2);
1152 math_Vector V2(1, nbP3d*3+nbP2d*2);
1153 FirstTangencyVector(Line, myfirstpt, V1);
1154 lambda1 = SearchFirstLambda(Line, Para, V1, myfirstpt);
1156 LastTangencyVector(Line, mylastpt, V2);
1157 lambda2 = SearchLastLambda(Line, Para, V2, mylastpt);
1159 Approx_ParLeastSquareOfMyGradient
1160 LSQ(Line, myfirstpt, mylastpt,
1161 Cons, Cons, Para, deg+1);
1163 lambda1 = lambda1/deg;
1164 lambda2 = lambda2/deg;
1165 LSQ.Perform(Para, V1, V2, lambda1, lambda2);
1166 mydone = LSQ.IsDone();
1167 mySCU = LSQ.BezierValue();
1170 Standard_Real Fv, TheTol3d, TheTol2d;
1171 LSQ.Error(Fv, TheTol3d, TheTol2d);
1173 // Stockage de la multicurve approximee.
1174 tolreached = Standard_True;
1176 if (mydebug) DUMP(mySCU);
1178 myMultiCurves.Append(mySCU);
1179 Handle(TColStd_HArray1OfReal) ThePar =
1180 new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1181 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1182 ThePar->SetValue(i, Para(i));
1184 myPar.Append(ThePar);
1185 Tolers3d.Append(TheTol3d);
1186 Tolers2d.Append(TheTol2d);
1187 return Standard_True;
1194 void Approx_ComputeLine::Init(const Standard_Integer degreemin,
1195 const Standard_Integer degreemax,
1196 const Standard_Real Tolerance3d,
1197 const Standard_Real Tolerance2d,
1198 const Standard_Integer NbIterations,
1199 const Standard_Boolean cutting,
1200 const Approx_ParametrizationType parametrization,
1201 const Standard_Boolean Squares)
1203 mydegremin = degreemin;
1204 mydegremax = degreemax;
1205 mytol3d = Tolerance3d;
1206 mytol2d = Tolerance2d;
1207 Par = parametrization;
1208 mysquares = Squares;
1210 myitermax = NbIterations;
1215 void Approx_ComputeLine::SetDegrees(const Standard_Integer degreemin,
1216 const Standard_Integer degreemax)
1218 mydegremin = degreemin;
1219 mydegremax = degreemax;
1223 void Approx_ComputeLine::SetTolerances(const Standard_Real Tolerance3d,
1224 const Standard_Real Tolerance2d)
1226 mytol3d = Tolerance3d;
1227 mytol2d = Tolerance2d;
1231 void Approx_ComputeLine::SetConstraints(const AppParCurves_Constraint FirstC,
1232 const AppParCurves_Constraint LastC)
1240 Standard_Boolean Approx_ComputeLine::IsAllApproximated()
1245 Standard_Boolean Approx_ComputeLine::IsToleranceReached()
1250 void Approx_ComputeLine::Error(const Standard_Integer Index,
1251 Standard_Real& tol3d,
1252 Standard_Real& tol2d) const
1254 tol3d = Tolers3d.Value(Index);
1255 tol2d = Tolers2d.Value(Index);
1258 void Approx_ComputeLine::Parametrization(Approx_ParametrizationType& partype) const