1 // Created on: 1993-09-07
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // modified by NIZHNY-OFV Thu Jan 20 11:04:19 2005
19 #include <ProjLib_ComputeApprox.hxx>
21 #include <GeomAbs_SurfaceType.hxx>
22 #include <GeomAbs_CurveType.hxx>
23 #include <AppCont_Function.hxx>
24 #include <Convert_CompBezierCurves2dToBSplineCurve2d.hxx>
27 #include <BSplCLib.hxx>
28 #include <Standard_NoSuchObject.hxx>
29 #include <Geom_UndefinedDerivative.hxx>
31 #include <gp_Trsf.hxx>
32 #include <Precision.hxx>
33 #include <Approx_FitAndDivide2d.hxx>
34 #include <AppParCurves_MultiCurve.hxx>
35 #include <Adaptor3d_HCurve.hxx>
36 #include <Adaptor3d_HSurface.hxx>
37 #include <TColgp_Array1OfPnt2d.hxx>
38 #include <TColgp_Array1OfPnt.hxx>
39 #include <TColStd_Array1OfReal.hxx>
40 #include <TColStd_Array1OfInteger.hxx>
41 #include <Geom_BSplineCurve.hxx>
42 #include <Geom_BezierCurve.hxx>
43 #include <Geom2d_BSplineCurve.hxx>
44 #include <Geom2d_BezierCurve.hxx>
48 #include <DrawTrSurf.hxx>
51 //static Standard_Boolean AffichValue = Standard_False;
54 //=======================================================================
57 //=======================================================================
59 static inline Standard_Boolean IsEqual(Standard_Real Check,Standard_Real With,Standard_Real Toler)
61 return ((Abs(Check - With) < Toler) ? Standard_True : Standard_False);
65 //=======================================================================
68 //=======================================================================
70 static gp_Pnt2d Function_Value(const Standard_Real U,
71 const Handle(Adaptor3d_HCurve)& myCurve,
72 const Handle(Adaptor3d_HSurface)& mySurface,
73 const Standard_Real U1,
74 const Standard_Real U2,
75 const Standard_Real V1,
76 const Standard_Real V2,
77 const Standard_Boolean UCouture,
78 const Standard_Boolean VCouture )
80 Standard_Real S = 0., T = 0.;
82 gp_Pnt P3d = myCurve->Value(U);
83 GeomAbs_SurfaceType SType = mySurface->GetType();
89 gp_Pln Plane = mySurface->Plane();
90 ElSLib::Parameters( Plane, P3d, S, T);
93 case GeomAbs_Cylinder:
95 gp_Cylinder Cylinder = mySurface->Cylinder();
96 ElSLib::Parameters( Cylinder, P3d, S, T);
101 gp_Cone Cone = mySurface->Cone();
102 ElSLib::Parameters( Cone, P3d, S, T);
107 gp_Sphere Sphere = mySurface->Sphere();
108 ElSLib::Parameters(Sphere, P3d, S, T);
113 gp_Torus Torus = mySurface->Torus();
114 ElSLib::Parameters( Torus, P3d, S, T);
118 Standard_NoSuchObject::Raise("ProjLib_ComputeApprox::Value");
124 S = ElCLib::InPeriod(S, U1, U2);
129 if(SType == GeomAbs_Sphere) {
130 if ( Abs( S - U1 ) > M_PI ) {
135 S = ElCLib::InPeriod(S, U1, U2);
138 T = ElCLib::InPeriod(T, V1, V2);
141 return gp_Pnt2d(S, T);
143 //=======================================================================
146 //=======================================================================
147 static Standard_Boolean Function_D1( const Standard_Real U,
150 const Handle(Adaptor3d_HCurve)& myCurve,
151 const Handle(Adaptor3d_HSurface)& mySurface,
152 const Standard_Real U1,
153 const Standard_Real U2,
154 const Standard_Real V1,
155 const Standard_Real V2,
156 const Standard_Boolean UCouture,
157 const Standard_Boolean VCouture )
160 Standard_Real dU, dV;
162 P = Function_Value(U,myCurve,mySurface,U1,U2,V1,V2,UCouture,VCouture);
164 GeomAbs_SurfaceType Type = mySurface->GetType();
169 case GeomAbs_Cylinder:
175 myCurve->D1(U,P3d,T);
176 mySurface->D1(P.X(),P.Y(),P3d,D1U,D1V);
180 Standard_Real Nu = D1U.SquareMagnitude();
181 Standard_Real Nv = D1V.SquareMagnitude();
183 if ( Nu < Epsilon(1.) || Nv < Epsilon(1.))
184 return Standard_False;
188 D = gp_Vec2d( dU, dV);
193 return Standard_False;
196 return Standard_True;
199 //=======================================================================
200 //function : Function_SetUVBounds
202 //=======================================================================
203 static void Function_SetUVBounds(Standard_Real& myU1,
207 Standard_Boolean& UCouture,
208 Standard_Boolean& VCouture,
209 const Handle(Adaptor3d_HCurve)& myCurve,
210 const Handle(Adaptor3d_HSurface)& mySurface)
212 Standard_Real W1, W2, W;
215 W1 = myCurve->FirstParameter();
216 W2 = myCurve->LastParameter ();
218 // on ouvre l`intervalle
221 P1 = myCurve->Value(W1);
222 P2 = myCurve->Value(W2);
223 P = myCurve->Value(W);
225 switch ( mySurface->GetType()) {
228 gp_Cone Cone = mySurface->Cone();
229 VCouture = Standard_False;
231 switch( myCurve->GetType() ){
232 case GeomAbs_Parabola:
233 case GeomAbs_Hyperbola:
234 case GeomAbs_Ellipse:{
235 Standard_Real U1, U2, V1, V2, U , V;
236 ElSLib::Parameters( Cone, P1, U1, V1);
237 ElSLib::Parameters( Cone, P2, U2, V2);
238 ElSLib::Parameters( Cone, P , U , V );
241 if ( ( U1 < U && U < U2 ) && !myCurve->IsClosed() ) {
242 UCouture = Standard_False;
245 UCouture = Standard_True;
246 myU2 = myU1 + 2*M_PI;
252 Standard_Real U1, V1, U , V, Delta = 0., d = 0., pmin = W1, pmax = W1, dmax = 0., Uf, Ul;
253 ElSLib::Parameters( Cone, P1, U1, V1);
254 ElSLib::Parameters( Cone, P2, Ul, V1);
255 myU1 = U1; myU2 = U1; Uf = U1;
256 Standard_Real Step = .1;
257 Standard_Integer nbp = (Standard_Integer)((W2 - W1) / Step + 1);
259 Step = (W2 - W1) / (nbp - 1);
260 Standard_Boolean isclandper = (!(myCurve->IsClosed()) && !(myCurve->IsPeriodic()));
261 Standard_Boolean isFirst = Standard_True;
262 for(Standard_Real par = W1 + Step; par <= W2; par += Step)
264 if(!isclandper) par += Step;
265 P = myCurve->Value(par);
266 ElSLib::Parameters( Cone, P, U, V);
271 if( ( (IsEqual(U,(2*M_PI),1.e-10) && (U1 >= 0. && U1 <= M_PI)) &&
272 (IsEqual(U,Ul,1.e-10) && !IsEqual(Uf,0.,1.e-10)) ) && isclandper )
276 // Protection against first-last point on seam.
279 else if (par + Step >= W2)
289 if( ( (IsEqual(U,0.,1.e-10) && (U1 >= M_PI && U1 <= (2*M_PI))) &&
290 (IsEqual(U,Ul,1.e-10) && !IsEqual(Uf,(2*M_PI),1.e-10)) ) && isclandper )
294 // Protection against first-last point on seam.
297 else if (par + Step >= W2)
305 dmax = Max(dmax, Abs(d));
306 if(U < myU1) {myU1 = U; pmin = par;}
307 if(U > myU2) {myU2 = U; pmax = par;}
309 isFirst = Standard_False;
310 } // for(Standard_Real par = W1 + Step; par <= W2; par += Step)
312 if(!(Abs(pmin - W1) <= Precision::PConfusion() || Abs(pmin - W2) <= Precision::PConfusion()) ) myU1 -= dmax*.5;
313 if(!(Abs(pmax - W1) <= Precision::PConfusion() || Abs(pmax - W2) <= Precision::PConfusion()) ) myU2 += dmax*.5;
315 if((myU1 >=0. && myU1 <= 2*M_PI) && (myU2 >=0. && myU2 <= 2*M_PI) ) UCouture = Standard_False;
317 U = ( myU1 + myU2 ) /2.;
320 UCouture = Standard_True;
324 }// switch curve type
328 case GeomAbs_Cylinder: {
329 gp_Cylinder Cylinder = mySurface->Cylinder();
330 VCouture = Standard_False;
332 if (myCurve->GetType() == GeomAbs_Ellipse) {
334 Standard_Real U1, U2, V1, V2, U , V;
335 ElSLib::Parameters( Cylinder, P1, U1, V1);
336 ElSLib::Parameters( Cylinder, P2, U2, V2);
337 ElSLib::Parameters( Cylinder, P , U , V );
341 if ( !myCurve->IsClosed()) {
342 if ( myU1 < U && U < myU2) {
343 U = ( myU1 + myU2 ) /2.;
348 U = ( myU1 + myU2 ) /2.;
358 UCouture = Standard_True;
364 myCurve->D1(W1,P3d,T);
365 mySurface->D1(U1,U2,P3d,D1U,D1V);
366 Standard_Real dU = T.Dot(D1U);
368 UCouture = Standard_True;
370 myU2 = myU1 + 2*M_PI;
379 Standard_Real U1, V1, U , V;
380 ElSLib::Parameters( Cylinder, P1, U1, V1);
381 Standard_Real Step = .1, Delta = 0.;
382 Standard_Real eps = M_PI, dmax = 0., d = 0.;
383 Standard_Integer nbp = (Standard_Integer)((W2 - W1) / Step + 1);
385 Step = (W2 - W1) / (nbp - 1);
386 myU1 = U1; myU2 = U1;
387 Standard_Real pmin = W1, pmax = W1, plim = W2+.1*Step;
388 for(Standard_Real par = W1 + Step; par <= plim; par += Step) {
389 P = myCurve->Value(par);
390 ElSLib::Parameters( Cylinder, P, U, V);
405 dmax = Max(dmax, Abs(d));
406 if(U < myU1) {myU1 = U; pmin = par;}
407 if(U > myU2) {myU2 = U; pmax = par;}
411 if(!(Abs(pmin - W1) <= Precision::PConfusion() ||
412 Abs(pmin - W2) <= Precision::PConfusion()) ) myU1 -= dmax*.5;
413 if(!(Abs(pmax - W1) <= Precision::PConfusion() ||
414 Abs(pmax - W2) <= Precision::PConfusion()) ) myU2 += dmax*.5;
416 if((myU1 >=0. && myU1 <= 2*M_PI) &&
417 (myU2 >=0. && myU2 <= 2*M_PI) ) {
418 UCouture = Standard_False;
421 U = ( myU1 + myU2 ) /2.;
424 UCouture = Standard_True;
430 case GeomAbs_Sphere:{
431 VCouture = Standard_False;
432 gp_Sphere SP = mySurface->Sphere();
433 if ( myCurve->GetType() == GeomAbs_Circle) {
434 UCouture = Standard_True;
436 // on cherche a savoir le nombre de fois que la couture est
438 // si 0 ou 2 fois : la PCurve est fermee et dans l`intervalle
439 // [Uc-PI, Uc+PI] (Uc: U du centre du cercle)
440 // si 1 fois : la PCurve est ouverte et dans l`intervalle
443 // pour determiner le nombre de solution, on resoud le systeme
444 // x^2 + y^2 + z^2 = R^2 (1)
445 // A x + B y + C z + D = 0 (2)
448 // REM : (1) (2) : equation du cercle
449 // (1) (3) (4) : equation de la couture.
450 Standard_Integer NbSolutions = 0;
451 Standard_Real A, B, C, D, R, Tol = 1.e-10;
452 Standard_Real U1, U2, V1, V2;
455 gp_Circ Circle = myCurve->Circle();
456 Trsf.SetTransformation(SP.Position());
457 Circle.Transform(Trsf);
460 gp_Pln Plane( gp_Ax3(Circle.Position()));
461 Plane.Coefficients(A,B,C,D);
466 if ( ( R - Abs(D/A)) > Tol) NbSolutions = 2;
467 else if ( Abs(R - Abs(D/A))< Tol) NbSolutions = 1;
468 else NbSolutions = 0;
473 Standard_Real delta = R*R*(A*A+C*C) - D*D;
475 if ( Abs(delta) < Tol*Tol) {
476 if ( A*D > 0.) NbSolutions = 1;
478 else if ( delta > 0) {
483 if ( xx > Tol) NbSolutions++;
486 if ( xx > Tol) NbSolutions++;
492 Standard_Real UU = 0.;
493 ElSLib::Parameters(SP, P1, U1, V1);
494 Standard_Real eps = 10.*Epsilon(1.);
495 Standard_Real dt = Max(Precision::PConfusion(), 0.01*(W2-W1));
498 //May be U1 must be equal 2*PI?
499 gp_Pnt Pd = myCurve->Value(W1+dt);
500 Standard_Real ud, vd;
501 ElSLib::Parameters(SP, Pd, ud, vd);
502 if(Abs(U1 - ud) > M_PI)
507 else if(Abs(2.*M_PI - U1) < eps)
510 gp_Pnt Pd = myCurve->Value(W1+dt);
511 Standard_Real ud, vd;
512 ElSLib::Parameters(SP, Pd, ud, vd);
513 if(Abs(U1 - ud) > M_PI)
519 ElSLib::Parameters(SP, P2, U2, V1);
522 //May be U2 must be equal 2*PI?
523 gp_Pnt Pd = myCurve->Value(W2-dt);
524 Standard_Real ud, vd;
525 ElSLib::Parameters(SP, Pd, ud, vd);
526 if(Abs(U2 - ud) > M_PI)
531 else if(Abs(2.*M_PI - U2) < eps)
534 gp_Pnt Pd = myCurve->Value(W2-dt);
535 Standard_Real ud, vd;
536 ElSLib::Parameters(SP, Pd, ud, vd);
537 if(Abs(U2 - ud) > M_PI)
543 ElSLib::Parameters(SP, P, UU, V1);
544 //+This fragment was the reason of bug # 26008.
545 //+It has been deleted on April, 03 2015.
546 //Standard_Real UUmi = Min(Min(U1,UU),Min(UU,U2));
547 //Standard_Real UUma = Max(Max(U1,UU),Max(UU,U2));
548 //Standard_Boolean reCalc = ((UUmi >= 0. && UUmi <= M_PI) && (UUma >= 0. && UUma <= M_PI));
550 P2 = myCurve->Value(W1+M_PI/8);
551 ElSLib::Parameters(SP,P2,U2,V2);
553 if ( NbSolutions == 1) {
554 if ( Abs(U1-U2) > M_PI) { // on traverse la couture
564 else { // on ne traverse pas la couture
575 else { // 0 ou 2 solutions
576 gp_Pnt Center = Circle.Location();
578 ElSLib::SphereParameters(gp_Ax3(gp::XOY()),1,Center, U, V);
583 // eval the VCouture.
584 if ( (C==0) || Abs(Abs(D/C)-R) > 1.e-10) {
585 VCouture = Standard_False;
588 VCouture = Standard_True;
589 UCouture = Standard_True;
593 myV2 = 3 * M_PI / 2.;
596 myV1 = -3 * M_PI / 2.;
600 // si P1.Z() vaut +/- R on est sur le sommet : pas significatif.
601 gp_Pnt pp = P1.Transformed(Trsf);
603 if ( Abs( Abs(pp.Z()) - R) < Tol) {
604 gp_Pnt Center = Circle.Location();
606 ElSLib::SphereParameters(gp_Ax3(gp::XOY()),1,Center, U, V);
609 VCouture = Standard_False;
614 myV1 = -1.e+100; myV2 = 1.e+100;
616 //+This fragment was the reason of bug # 26008.
617 //+It has been deleted on April, 03 2015.
618 //Standard_Real UU1 = myU1, UU2 = myU2;
619 //if((Abs(UU1) <= (2.*M_PI) && Abs(UU2) <= (2.*M_PI)) && NbSolutions == 1 && reCalc) {
620 // gp_Pnt Center = Circle.Location();
621 // Standard_Real U,V;
622 // ElSLib::SphereParameters(gp_Ax3(gp::XOY()),1,Center, U, V);
624 // myU1 = Min(UU1,myU1);
625 // myU2 = myU1 + 2.*M_PI;
629 }//if ( myCurve->GetType() == GeomAbs_Circle)
632 Standard_Real U1, V1, U , V;
633 ElSLib::Parameters( SP, P1, U1, V1);
634 Standard_Real Step = .1, Delta = 0.;
635 Standard_Real eps = M_PI, dmax = 0., d = 0.;
636 Standard_Integer nbp = (Standard_Integer)((W2 - W1) / Step + 1);
638 Step = (W2 - W1) / (nbp - 1);
639 myU1 = U1; myU2 = U1;
640 Standard_Real pmin = W1, pmax = W1, plim = W2+.1*Step;
641 for(Standard_Real par = W1 + Step; par <= plim; par += Step) {
642 P = myCurve->Value(par);
643 ElSLib::Parameters( SP, P, U, V);
658 dmax = Max(dmax, Abs(d));
659 if(U < myU1) {myU1 = U; pmin = par;}
660 if(U > myU2) {myU2 = U; pmax = par;}
664 if(!(Abs(pmin - W1) <= Precision::PConfusion() ||
665 Abs(pmin - W2) <= Precision::PConfusion()) ) myU1 -= dmax*.5;
666 if(!(Abs(pmax - W1) <= Precision::PConfusion() ||
667 Abs(pmax - W2) <= Precision::PConfusion()) ) myU2 += dmax*.5;
669 if((myU1 >=0. && myU1 <= 2*M_PI) &&
670 (myU2 >=0. && myU2 <= 2*M_PI) ) {
673 UCouture = Standard_False;
676 U = ( myU1 + myU2 ) /2.;
679 UCouture = Standard_True;
682 VCouture = Standard_False;
688 gp_Torus TR = mySurface->Torus();
689 Standard_Real U1, V1, U , V;
690 ElSLib::Parameters( TR, P1, U1, V1);
691 Standard_Real Step = .1, DeltaU = 0., DeltaV = 0.;
692 Standard_Real eps = M_PI, dmaxU = 0., dU = 0., dmaxV = 0., dV = 0.;
693 Standard_Integer nbp = (Standard_Integer)((W2 - W1) / Step + 1);
695 Step = (W2 - W1) / (nbp - 1);
696 myU1 = U1; myU2 = U1;
697 myV1 = V1; myV2 = V1;
698 Standard_Real pminU = W1, pmaxU = W1, pminV = W1, pmaxV = W1,
700 for(Standard_Real par = W1 + Step; par <= plim; par += Step) {
701 P = myCurve->Value(par);
702 ElSLib::Parameters( TR, P, U, V);
731 dmaxU = Max(dmaxU, Abs(dU));
732 dmaxV = Max(dmaxV, Abs(dV));
733 if(U < myU1) {myU1 = U; pminU = par;}
734 if(U > myU2) {myU2 = U; pmaxU = par;}
735 if(V < myV1) {myV1 = V; pminV = par;}
736 if(V > myV2) {myV2 = V; pmaxV = par;}
741 if(!(Abs(pminU - W1) <= Precision::PConfusion() ||
742 Abs(pminU - W2) <= Precision::PConfusion()) ) myU1 -= dmaxU*.5;
743 if(!(Abs(pmaxU - W1) <= Precision::PConfusion() ||
744 Abs(pmaxU - W2) <= Precision::PConfusion()) ) myU2 += dmaxU*.5;
745 if(!(Abs(pminV - W1) <= Precision::PConfusion() ||
746 Abs(pminV - W2) <= Precision::PConfusion()) ) myV1 -= dmaxV*.5;
747 if(!(Abs(pmaxV - W1) <= Precision::PConfusion() ||
748 Abs(pmaxV - W2) <= Precision::PConfusion()) ) myV2 += dmaxV*.5;
750 if((myU1 >=0. && myU1 <= 2*M_PI) &&
751 (myU2 >=0. && myU2 <= 2*M_PI) ) {
754 UCouture = Standard_False;
757 U = ( myU1 + myU2 ) /2.;
760 UCouture = Standard_True;
762 if((myV1 >=0. && myV1 <= 2*M_PI) &&
763 (myV2 >=0. && myV2 <= 2*M_PI) ) {
764 VCouture = Standard_False;
767 V = ( myV1 + myV2 ) /2.;
770 VCouture = Standard_True;
778 UCouture = Standard_False;
779 VCouture = Standard_False;
786 //=======================================================================
787 //classn : ProjLib_Function
789 //=======================================================================
790 class ProjLib_Function : public AppCont_Function
792 Handle(Adaptor3d_HCurve) myCurve;
793 Handle(Adaptor3d_HSurface) mySurface;
794 Standard_Boolean myIsPeriodic[2];
795 Standard_Real myPeriod[2];
798 Standard_Real myU1,myU2,myV1,myV2;
799 Standard_Boolean UCouture,VCouture;
801 ProjLib_Function(const Handle(Adaptor3d_HCurve)& C,
802 const Handle(Adaptor3d_HSurface)& S)
809 UCouture(Standard_False),
810 VCouture(Standard_False)
814 Function_SetUVBounds(myU1,myU2,myV1,myV2,UCouture,VCouture,myCurve,mySurface);
815 myIsPeriodic[0] = mySurface->IsUPeriodic();
816 myIsPeriodic[1] = mySurface->IsVPeriodic();
819 myPeriod[0] = mySurface->UPeriod();
824 myPeriod[1] = mySurface->VPeriod();
829 void PeriodInformation(const Standard_Integer theDimIdx,
830 Standard_Boolean& IsPeriodic,
831 Standard_Real& thePeriod) const
833 IsPeriodic = myIsPeriodic[theDimIdx - 1];
834 thePeriod = myPeriod[theDimIdx - 1];
837 Standard_Real FirstParameter() const
839 return (myCurve->FirstParameter());
842 Standard_Real LastParameter() const
844 return (myCurve->LastParameter());
847 Standard_Boolean Value(const Standard_Real theT,
848 NCollection_Array1<gp_Pnt2d>& thePnt2d,
849 NCollection_Array1<gp_Pnt>& /*thePnt*/) const
851 thePnt2d(1) = Function_Value(theT, myCurve, mySurface, myU1, myU2, myV1, myV2, UCouture, VCouture);
852 return Standard_True;
855 gp_Pnt2d Value(const Standard_Real theT) const
857 return Function_Value(theT, myCurve, mySurface, myU1, myU2, myV1, myV2, UCouture, VCouture);
860 Standard_Boolean D1(const Standard_Real theT,
861 NCollection_Array1<gp_Vec2d>& theVec2d,
862 NCollection_Array1<gp_Vec>& /*theVec*/) const
866 Standard_Boolean isOk = Function_D1(theT, aPnt2d,aVec2d, myCurve, mySurface, myU1, myU2, myV1, myV2, UCouture, VCouture);
867 theVec2d(1) = aVec2d;
872 //=======================================================================
873 //function : ProjLib_ComputeApprox
875 //=======================================================================
877 ProjLib_ComputeApprox::ProjLib_ComputeApprox
878 (const Handle(Adaptor3d_HCurve) & C,
879 const Handle(Adaptor3d_HSurface) & S,
880 const Standard_Real Tol )
882 // if the surface is a plane and the curve a BSpline or a BezierCurve,
883 // don`t make an Approx but only the projection of the poles.
885 myTolerance = Max(Precision::PApproximation(),Tol);
886 Standard_Integer NbKnots, NbPoles ;
887 GeomAbs_CurveType CType = C->GetType();
888 GeomAbs_SurfaceType SType = S->GetType();
890 Standard_Boolean SurfIsAnal = (SType != GeomAbs_BSplineSurface) &&
891 (SType != GeomAbs_BezierSurface) &&
892 (SType != GeomAbs_OtherSurface) ;
894 Standard_Boolean CurvIsAnal = (CType != GeomAbs_BSplineCurve) &&
895 (CType != GeomAbs_BezierCurve) &&
896 (CType != GeomAbs_OffsetCurve) &&
897 (CType != GeomAbs_OtherCurve) ;
899 Standard_Boolean simplecase = SurfIsAnal && CurvIsAnal;
901 if (CType == GeomAbs_BSplineCurve &&
902 SType == GeomAbs_Plane ) {
904 // get the poles and eventually the weights
905 Handle(Geom_BSplineCurve) BS = C->BSpline();
906 NbPoles = BS->NbPoles();
907 TColgp_Array1OfPnt P3d( 1, NbPoles);
908 TColgp_Array1OfPnt2d Poles( 1, NbPoles);
909 TColStd_Array1OfReal Weights( 1, NbPoles);
910 if ( BS->IsRational()) BS->Weights(Weights);
912 gp_Pln Plane = S->Plane();
914 for ( Standard_Integer i = 1; i <= NbPoles; i++) {
915 ElSLib::Parameters( Plane, P3d(i), U, V);
916 Poles.SetValue(i,gp_Pnt2d(U,V));
918 NbKnots = BS->NbKnots();
919 TColStd_Array1OfReal Knots(1,NbKnots);
920 TColStd_Array1OfInteger Mults(1,NbKnots);
922 BS->Multiplicities(Mults) ;
923 // get the knots and mults if BSplineCurve
924 if ( BS->IsRational()) {
925 myBSpline = new Geom2d_BSplineCurve(Poles,
933 myBSpline = new Geom2d_BSplineCurve(Poles,
940 else if (CType == GeomAbs_BezierCurve &&
941 SType == GeomAbs_Plane ) {
943 // get the poles and eventually the weights
944 Handle(Geom_BezierCurve) BezierCurvePtr = C->Bezier() ;
945 NbPoles = BezierCurvePtr->NbPoles();
946 TColgp_Array1OfPnt P3d( 1, NbPoles);
947 TColgp_Array1OfPnt2d Poles( 1, NbPoles);
948 TColStd_Array1OfReal Weights( 1, NbPoles);
949 if ( BezierCurvePtr->IsRational()) {
950 BezierCurvePtr->Weights(Weights);
952 BezierCurvePtr->Poles( P3d);
954 // project the 3D-Poles on the plane
956 gp_Pln Plane = S->Plane();
958 for ( Standard_Integer i = 1; i <= NbPoles; i++) {
959 ElSLib::Parameters( Plane, P3d(i), U, V);
960 Poles.SetValue(i,gp_Pnt2d(U,V));
962 if ( BezierCurvePtr->IsRational()) {
963 myBezier = new Geom2d_BezierCurve(Poles, Weights);
966 myBezier = new Geom2d_BezierCurve(Poles);
970 ProjLib_Function F( C, S);
973 //if ( AffichValue) {
974 // Standard_Integer Nb = 20;
975 // Standard_Real U1, U2, dU, U;
976 // U1 = F.FirstParameter();
977 // U2 = F.LastParameter();
978 // dU = ( U2 - U1) / Nb;
979 // TColStd_Array1OfInteger Mults(1,Nb+1);
980 // TColStd_Array1OfReal Knots(1,Nb+1);
981 // TColgp_Array1OfPnt2d Poles(1,Nb+1);
982 // for ( Standard_Integer i = 1; i <= Nb+1; i++) {
983 // U = U1 + (i-1)*dU;
984 // Poles(i) = F.Value(U);
985 // cout << "i = " << i << ": U = " << U <<
986 // ", p(" << Poles(i).X() << ", " << Poles(i).Y() << ");" << endl;
993 //2D-curve for showing in DRAW
994 // Handle(Geom2d_Curve) aCC = new Geom2d_BSplineCurve(Poles,Knots,Mults,1);
995 // AffichValue = Standard_False;
1000 Standard_Integer Deg1, Deg2;
1010 Approx_FitAndDivide2d Fit(F,Deg1,Deg2,myTolerance,myTolerance,
1012 if(Fit.IsAllApproximated()) {
1014 Standard_Integer NbCurves = Fit.NbMultiCurves();
1016 // on essaie de rendre la courbe au moins C1
1017 Convert_CompBezierCurves2dToBSplineCurve2d Conv;
1020 Standard_Real Tol3d,Tol2d;
1021 for (i = 1; i <= NbCurves; i++) {
1022 Fit.Error(i,Tol3d, Tol2d);
1023 myTolerance = Max(myTolerance, Tol2d);
1024 AppParCurves_MultiCurve MC = Fit.Value( i); //Charge la Ieme Curve
1025 TColgp_Array1OfPnt2d Poles2d( 1, MC.Degree() + 1);//Recupere les poles
1026 MC.Curve(1, Poles2d);
1028 Conv.AddCurve(Poles2d);
1031 //mise a jour des fields de ProjLib_Approx
1033 NbPoles = Conv.NbPoles();
1034 NbKnots = Conv.NbKnots();
1036 if(NbPoles <= 0 || NbPoles > 100000)
1038 if(NbKnots <= 0 || NbKnots > 100000)
1041 TColgp_Array1OfPnt2d NewPoles(1,NbPoles);
1042 TColStd_Array1OfReal NewKnots(1,NbKnots);
1043 TColStd_Array1OfInteger NewMults(1,NbKnots);
1045 Conv.KnotsAndMults(NewKnots,NewMults);
1046 Conv.Poles(NewPoles);
1048 BSplCLib::Reparametrize(C->FirstParameter(),
1053 for (int i = 1; i <= NbPoles; i++)
1055 cout << NewPoles.Value(i).X() << " " << NewPoles.Value(i).Y() << endl;
1059 // il faut recadrer les poles de debut et de fin:
1060 // ( Car pour les problemes de couture, on a du ouvrir l`intervalle
1061 // de definition de la courbe.)
1062 // On choisit de calculer ces poles par prolongement de la courbe
1064 myBSpline = new Geom2d_BSplineCurve (NewPoles,
1070 Standard_Integer NbCurves = Fit.NbMultiCurves();
1072 Standard_Real Tol3d,Tol2d;
1073 Fit.Error(NbCurves,Tol3d, Tol2d);
1074 myTolerance = Tol2d;
1079 Standard_Real UFirst = F.FirstParameter();
1080 gp_Pnt P3d = C->Value( UFirst );
1081 Standard_Real u = 0., v = 0.;
1086 gp_Pln Plane = S->Plane();
1087 ElSLib::Parameters( Plane, P3d, u, v );
1090 case GeomAbs_Cylinder:
1092 gp_Cylinder Cylinder = S->Cylinder();
1093 ElSLib::Parameters( Cylinder, P3d, u, v );
1098 gp_Cone Cone = S->Cone();
1099 ElSLib::Parameters( Cone, P3d, u, v );
1102 case GeomAbs_Sphere:
1104 gp_Sphere Sphere = S->Sphere();
1105 ElSLib::Parameters( Sphere, P3d, u, v );
1110 gp_Torus Torus = S->Torus();
1111 ElSLib::Parameters( Torus, P3d, u, v );
1115 Standard_NoSuchObject::Raise("ProjLib_ComputeApprox::Value");
1117 Standard_Boolean ToMirror = Standard_False;
1118 Standard_Real du = 0., dv = 0.;
1119 Standard_Integer number;
1122 if (SType == GeomAbs_Sphere && Abs(u-F.myU1) > M_PI)
1124 ToMirror = Standard_True;
1128 Standard_Real newV = ElCLib::InPeriod( v, F.myV1, F.myV2 );
1129 number = (Standard_Integer) (Floor((newV-v)/(F.myV2-F.myV1)));
1130 dv -= number*(F.myV2-F.myV1);
1132 if (F.UCouture || (F.VCouture && SType == GeomAbs_Sphere))
1134 Standard_Real aNbPer;
1135 gp_Pnt2d P2d = F.Value(UFirst);
1137 du = (du < 0) ? (du - Precision::PConfusion()) :
1138 (du + Precision::PConfusion());
1139 modf(du/M_PI, &aNbPer);
1140 number = (Standard_Integer)aNbPer;
1144 if (!myBSpline.IsNull())
1146 if (du != 0. || dv != 0.)
1147 myBSpline->Translate( gp_Vec2d(du,dv) );
1150 gp_Ax2d Axe( gp_Pnt2d(0.,0.), gp_Dir2d(1.,0.) );
1151 myBSpline->Mirror( Axe );
1157 //=======================================================================
1158 //function : BSpline
1160 //=======================================================================
1162 Handle(Geom2d_BSplineCurve) ProjLib_ComputeApprox::BSpline() const
1168 //=======================================================================
1171 //=======================================================================
1173 Handle(Geom2d_BezierCurve) ProjLib_ComputeApprox::Bezier() const
1180 //=======================================================================
1181 //function : Tolerance
1183 //=======================================================================
1185 Standard_Real ProjLib_ComputeApprox::Tolerance() const