// Created on: 1993-03-30 // Created by: Laurent BUCHARD // Copyright (c) 1993-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #include #include #include #include #include #include #include #include const Standard_Integer LimRajout = 5; const Standard_Integer NbPntMaxDecoupage = 30; const Standard_Real RatioTol = 1.5; //======================================================================= //function : MINABS3 //purpose : Compute minimal absolute distance to 0 from 3 values. //======================================================================= static Standard_Real MINABS3(Standard_Real a, Standard_Real b,Standard_Real c) { if(a<0.0) a=-a; if(b<0.0) b=-b; if(c<0.0) c=-c; if(a>c) a=c; if(a>b) a=b; return(a); } //======================================================================= //function : MINABS4 //purpose : Compute minimal absolute distance to 0 from 4 values. //======================================================================= static Standard_Real MINABS4(Standard_Real a, Standard_Real b,Standard_Real c,Standard_Real d) { if(a<0.0) a=-a; if(b<0.0) b=-b; if(c<0.0) c=-c; if(d<0.0) d=-d; if(a>c) a=c; if(a>b) a=b; if(a>d) a=d; return(a); } //======================================================================= //function : ComputeTrsf3d //purpose : //======================================================================= static void ComputeTrsf3d(const Handle(TheWLine)& theline, Standard_Real& Xo, Standard_Real& Ax, Standard_Real& Yo, Standard_Real& Ay, Standard_Real& Zo, Standard_Real& Az) { Standard_Integer nbp = theline->NbPnts(); Standard_Real z0,z1,x0,x1,y0,y1; z0=y0=x0=RealLast(); z1=y1=x1=RealFirst(); for(Standard_Integer i=1;i<=nbp;i++) { const gp_Pnt& P = theline->Point(i).Value(); Standard_Real X = P.X(); Standard_Real Y = P.Y(); Standard_Real Z = P.Z(); if(Xx1) x1=X; if(Yy1) y1=Y; if(Zz1) z1=Z; } Standard_Real dx = x1-x0; Standard_Real dy = y1-y0; Standard_Real dz = z1-z0; Standard_Real MaxD = dx; if(MaxD < dy) MaxD=dy; if(MaxD < dz) MaxD=dz; Standard_Real MaxDF = 0.01*MaxD; if(MaxDF<1e-12) MaxDF=1.0; if(dx > MaxDF) { Ax = 1.0 / dx; Xo = -Ax * x0; } else { Ax = 1.0/( MaxDF) ; Xo = -Ax*x0; } if(dy > MaxDF) { Ay = 1.0 / dy; Yo = -Ay * y0; } else { Ay = 1.0/( MaxDF); Yo = -Ay*y0; } if(dz > MaxDF) { Az = 1.0 / dz; Zo = -Az * z0; } else { Az = 1.0/(MaxDF); Zo = -Az*z0; } } //======================================================================= //function : ComputeTrsf2d //purpose : //======================================================================= static void ComputeTrsf2d(const Handle(TheWLine)& theline, Standard_Real& Uo, Standard_Real& Au, Standard_Real& Vo, Standard_Real& Av, const Standard_Boolean onFirst, const Standard_Real UVResRatio = 1.0) { Standard_Integer nbp = theline->NbPnts(); Standard_Real u0,u1,v0,v1; u0 = v0 = RealLast(); u1 = v1 = RealFirst(); // pointer to a member-function void (IntSurf_PntOn2S::* pfunc)(Standard_Real&,Standard_Real&) const; if (onFirst) pfunc = &IntSurf_PntOn2S::ParametersOnS1; else pfunc = &IntSurf_PntOn2S::ParametersOnS2; for(Standard_Integer i=1;i<=nbp;i++) { const IntSurf_PntOn2S& POn2S = theline->Point(i); Standard_Real U,V; (POn2S.*pfunc)(U,V); if(Uu1) u1=U; if(Vv1) v1=V; } Standard_Real du = (u1-u0); Standard_Real dv = (v1-v0); if (UVResRatio > 1.) du *= UVResRatio; else if (UVResRatio < 1.) dv /= UVResRatio; Standard_Real MaxUV=du; if(MaxUV MaxUVF) { Au = 1.0 / du; Uo = -Au * u0; } else { Au = 1.0/(MaxUVF); Uo = -Au*u0; } if(dv > MaxUVF) { Av = 1.0 / dv; Vo = -Av * v0; } else { Av = 1.0/(MaxUVF); Vo = -Av*v0; } } //======================================================================= //function : Parameters //purpose : //======================================================================= static void Parameters(const ApproxInt_TheMultiLine& Line, const Standard_Integer firstP, const Standard_Integer lastP, const Approx_ParametrizationType Par, math_Vector& TheParameters) { Standard_Integer i, j, nbP2d, nbP3d; Standard_Real dist; gp_Pnt P1, P2; gp_Pnt2d P12d, P22d; if (Par == Approx_ChordLength || Par == Approx_Centripetal) { nbP3d = ApproxInt_TheMultiLineTool::NbP3d(Line); nbP2d = ApproxInt_TheMultiLineTool::NbP2d(Line); Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d; if (nbP3d == 0) mynbP3d = 1; if (nbP2d == 0) mynbP2d = 1; TheParameters(firstP) = 0.0; dist = 0.0; TColgp_Array1OfPnt tabP(1, mynbP3d); TColgp_Array1OfPnt tabPP(1, mynbP3d); TColgp_Array1OfPnt2d tabP2d(1, mynbP2d); TColgp_Array1OfPnt2d tabPP2d(1, mynbP2d); for (i = firstP+1; i <= lastP; i++) { if (nbP3d != 0 && nbP2d != 0) ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP, tabP2d); else if (nbP2d != 0) ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP2d); else if (nbP3d != 0) ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP); if (nbP3d != 0 && nbP2d != 0) ApproxInt_TheMultiLineTool::Value(Line, i, tabPP, tabPP2d); else if (nbP2d != 0) ApproxInt_TheMultiLineTool::Value(Line, i, tabPP2d); else if (nbP3d != 0) ApproxInt_TheMultiLineTool::Value(Line, i, tabPP); dist = 0; for (j = 1; j <= nbP3d; j++) { P1 = tabP(j); P2 = tabPP(j); dist += P2.Distance(P1); } for (j = 1; j <= nbP2d; j++) { P12d = tabP2d(j); P22d = tabPP2d(j); dist += P22d.Distance(P12d); } if(Par == Approx_ChordLength) TheParameters(i) = TheParameters(i-1) + dist; else {// Par == Approx_Centripetal TheParameters(i) = TheParameters(i-1) + Sqrt(dist); } } for (i = firstP; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP); } else { for (i = firstP; i <= lastP; i++) { TheParameters(i) = (Standard_Real(i)-firstP)/ (Standard_Real(lastP)-Standard_Real(firstP)); } } } //======================================================================= //function : ApproxInt_Approx //purpose : Constructor. //======================================================================= ApproxInt_Approx::ApproxInt_Approx() : myComputeLine(4, 8, 0.001, 0.001, 5, Standard_True), myComputeLineBezier(4, 8, 0.001, 0.001, 5, Standard_True) { myComputeLine.SetContinuity(2); myData.myBezierApprox = Standard_True; myRelativeTol = Standard_True; myNbPntMax = NbPntMaxDecoupage; myData.myMinFactorXYZ = 0.0; myData.myMinFactorUV = 0.0; myTolReached3d = myTolReached2d = 0.0; myUVRes1 = myUVRes2 = 1.0; } //======================================================================= //function : Perform //purpose : Build without surfaces information. //======================================================================= void ApproxInt_Approx::Perform(const Handle(TheWLine)& theline, const Standard_Boolean ApproxXYZ, const Standard_Boolean ApproxU1V1, const Standard_Boolean ApproxU2V2, const Standard_Integer indicemin, const Standard_Integer indicemax) { // Prepare DS. prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax); Standard_Integer nbpntbez = indicemax-indicemin; if(nbpntbez < LimRajout) myData.myBezierApprox = Standard_False; else myData.myBezierApprox = Standard_True; // Fill data structure. fillData(theline, ApproxXYZ, ApproxU1V1, ApproxU2V2); // Build knots. buildKnots(theline, NULL); Standard_Boolean cut = Standard_True; if(myRelativeTol==Standard_False) { myComputeLine.Init(myDegMin, myDegMax, myTol3d*myData.myMinFactorXYZ, myTol2d*myData.myMinFactorUV, myNbIterMax, cut, myData.parametrization); myComputeLineBezier.Init(myDegMin, myDegMax, myTol3d*myData.myMinFactorXYZ, myTol2d*myData.myMinFactorUV, myNbIterMax, cut, myData.parametrization); } buildCurve(theline, NULL); } //======================================================================= //function : Perform //purpose : Param-Param perform. //======================================================================= void ApproxInt_Approx::Perform(const ThePSurface& Surf1, const ThePSurface& Surf2, const Handle(TheWLine)& theline, const Standard_Boolean ApproxXYZ, const Standard_Boolean ApproxU1V1, const Standard_Boolean ApproxU2V2, const Standard_Integer indicemin, const Standard_Integer indicemax) { GeomAbs_SurfaceType typeS1 = ThePSurfaceTool::GetType(Surf1); GeomAbs_SurfaceType typeS2 = ThePSurfaceTool::GetType(Surf2); if ((typeS1 != GeomAbs_Plane && typeS1 != GeomAbs_Cylinder && typeS1 != GeomAbs_Sphere && typeS1 != GeomAbs_Cone) && (typeS2 != GeomAbs_Plane && typeS2 != GeomAbs_Cylinder && typeS2 != GeomAbs_Sphere && typeS2 != GeomAbs_Cone)) { // Prepare DS. prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax); // Non-analytical case: Param-Param perform. ApproxInt_ThePrmPrmSvSurfaces myPrmPrmSvSurfaces(Surf1,Surf2); Standard_Integer nbpntbez = indicemax-indicemin; if(nbpntbez < LimRajout) myData.myBezierApprox = Standard_False; else myData.myBezierApprox = Standard_True; Standard_Boolean cut = Standard_True; if(nbpntbez < LimRajout) { cut = Standard_False; } Standard_Real aS1URes = ThePSurfaceTool::UResolution(Surf1, 1.0), aS1VRes = ThePSurfaceTool::VResolution(Surf1, 1.0), aS2URes = ThePSurfaceTool::UResolution(Surf2, 1.0), aS2VRes = ThePSurfaceTool::VResolution(Surf2, 1.0); if(ApproxU1V1) myUVRes1 = aS1URes / aS1VRes; if(ApproxU2V2) myUVRes2 = aS2URes / aS2VRes; // Fill data structure. fillData(theline, ApproxXYZ, ApproxU1V1, ApproxU2V2); // Build knots. Standard_Address ptrsvsurf = &myPrmPrmSvSurfaces; buildKnots(theline, ptrsvsurf); if(myRelativeTol==Standard_False) { myComputeLine.Init(myDegMin, myDegMax, myTol3d*myData.myMinFactorXYZ, myTol2d*myData.myMinFactorUV, myNbIterMax, cut, myData.parametrization); myComputeLineBezier.Init(myDegMin, myDegMax, myTol3d*myData.myMinFactorXYZ, myTol2d*myData.myMinFactorUV, myNbIterMax, cut, myData.parametrization); } else { myComputeLine.Init(myDegMin, myDegMax, myTol3d, myTol2d, myNbIterMax, cut, myData.parametrization); myComputeLineBezier.Init(myDegMin, myDegMax, myTol3d, myTol2d, myNbIterMax, cut, myData.parametrization); } buildCurve(theline, ptrsvsurf); } else { IntSurf_Quadric Quad; Standard_Boolean SecondIsImplicit=Standard_False; switch (typeS1) { case GeomAbs_Plane: Quad.SetValue(ThePSurfaceTool::Plane(Surf1)); break; case GeomAbs_Cylinder: Quad.SetValue(ThePSurfaceTool::Cylinder(Surf1)); break; case GeomAbs_Sphere: Quad.SetValue(ThePSurfaceTool::Sphere(Surf1)); break; case GeomAbs_Cone: Quad.SetValue(ThePSurfaceTool::Cone(Surf1)); break; default: { SecondIsImplicit = Standard_True; switch (typeS2) { case GeomAbs_Plane: Quad.SetValue(ThePSurfaceTool::Plane(Surf2)); break; case GeomAbs_Cylinder: Quad.SetValue(ThePSurfaceTool::Cylinder(Surf2)); break; case GeomAbs_Sphere: Quad.SetValue(ThePSurfaceTool::Sphere(Surf2)); break; case GeomAbs_Cone: Quad.SetValue(ThePSurfaceTool::Cone(Surf2)); break; default: break; } } break; } if(SecondIsImplicit) { Perform(Surf1,Quad,theline,ApproxXYZ,ApproxU1V1,ApproxU2V2,indicemin,indicemax); } else { Perform(Quad,Surf2,theline,ApproxXYZ,ApproxU1V1,ApproxU2V2,indicemin,indicemax); } } } //======================================================================= //function : SetParameters //purpose : //======================================================================= void ApproxInt_Approx::SetParameters(const Standard_Real Tol3d, const Standard_Real Tol2d, const Standard_Integer DegMin, const Standard_Integer DegMax, const Standard_Integer NbIterMax, const Standard_Boolean ApproxWithTangency, const Approx_ParametrizationType Parametrization) { myWithTangency = ApproxWithTangency; myTol3d = Tol3d / RatioTol; myTol2d = Tol2d / RatioTol; myDegMin = DegMin; myDegMax = DegMax; myNbIterMax = NbIterMax; myComputeLine.Init(myDegMin, myDegMax, myTol3d, myTol2d, myNbIterMax, Standard_True, Parametrization); if(!ApproxWithTangency) { myComputeLine.SetConstraints(AppParCurves_PassPoint,AppParCurves_PassPoint); } myComputeLineBezier.Init(myDegMin, myDegMax, myTol3d, myTol2d, myNbIterMax, Standard_True, Parametrization); if(!ApproxWithTangency) { myComputeLineBezier.SetConstraints(AppParCurves_PassPoint,AppParCurves_PassPoint); } myData.myBezierApprox = Standard_True; } //======================================================================= //function : SetParameters //purpose : Set parameters with RelativeTol flag and NbPntMax value. //======================================================================= void ApproxInt_Approx::SetParameters(const Standard_Real Tol3d, const Standard_Real Tol2d, const Standard_Boolean RelativeTol, const Standard_Integer DegMin, const Standard_Integer DegMax, const Standard_Integer NbIterMax, const Standard_Integer NbPntMax, const Standard_Boolean ApproxWithTangency, const Approx_ParametrizationType Parametrization) { myNbPntMax = NbPntMax ; myRelativeTol = RelativeTol ; SetParameters (Tol3d, Tol2d, DegMin, DegMax, NbIterMax, ApproxWithTangency, Parametrization) ; } //======================================================================= //function : Perform //purpose : Param-Analytic perform. //======================================================================= void ApproxInt_Approx::Perform(const ThePSurface& PSurf, const TheISurface& ISurf, const Handle(TheWLine)& theline, const Standard_Boolean ApproxXYZ, const Standard_Boolean ApproxU1V1, const Standard_Boolean ApproxU2V2, const Standard_Integer indicemin, const Standard_Integer indicemax) { // Prepare DS. prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax); // Non-analytical case: Param-Analytic perform. ApproxInt_TheImpPrmSvSurfaces myImpPrmSvSurfaces(PSurf,ISurf); Standard_Integer nbpntbez = indicemax-indicemin; if(nbpntbez < LimRajout) myData.myBezierApprox = Standard_False; else myData.myBezierApprox = Standard_True; Standard_Boolean cut = Standard_True; if(nbpntbez < LimRajout) { cut = Standard_False; } Standard_Real aS1URes = ThePSurfaceTool::UResolution(PSurf, 1.0), aS1VRes = ThePSurfaceTool::VResolution(PSurf, 1.0); if(ApproxU1V1) myUVRes1 = aS1URes / aS1VRes; // Fill data structure. fillData(theline, ApproxXYZ, ApproxU1V1, ApproxU2V2); // Build knots. Standard_Address ptrsvsurf = &myImpPrmSvSurfaces; buildKnots(theline, ptrsvsurf); if(myRelativeTol==Standard_False) { myComputeLine.Init(myDegMin, myDegMax, myTol3d*myData.myMinFactorXYZ, myTol2d*myData.myMinFactorUV, myNbIterMax, cut, myData.parametrization); myComputeLineBezier.Init(myDegMin, myDegMax, myTol3d*myData.myMinFactorXYZ, myTol2d*myData.myMinFactorUV, myNbIterMax, cut, myData.parametrization); } else { myComputeLine.Init(myDegMin, myDegMax, myTol3d, myTol2d, myNbIterMax, cut, myData.parametrization); myComputeLineBezier.Init(myDegMin, myDegMax, myTol3d, myTol2d, myNbIterMax, cut, myData.parametrization); } buildCurve(theline, ptrsvsurf); } //======================================================================= //function : Perform //purpose : Analytic-Param perform. //======================================================================= void ApproxInt_Approx::Perform(const TheISurface& ISurf, const ThePSurface& PSurf, const Handle(TheWLine)& theline, const Standard_Boolean ApproxXYZ, const Standard_Boolean ApproxU1V1, const Standard_Boolean ApproxU2V2, const Standard_Integer indicemin, const Standard_Integer indicemax) { // Prepare DS. prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax); // Non-analytical case: Analytic-Param perform. ApproxInt_TheImpPrmSvSurfaces myImpPrmSvSurfaces(ISurf, PSurf); Standard_Integer nbpntbez = indicemax-indicemin; if(nbpntbez < LimRajout) myData.myBezierApprox = Standard_False; else myData.myBezierApprox = Standard_True; Standard_Boolean cut = Standard_True; if(nbpntbez < LimRajout) { cut = Standard_False; } Standard_Real aS2URes = ThePSurfaceTool::UResolution(PSurf, 1.0), aS2VRes = ThePSurfaceTool::VResolution(PSurf, 1.0); if(ApproxU2V2) myUVRes2 = aS2URes / aS2VRes; // Fill data structure. fillData(theline, ApproxXYZ, ApproxU1V1, ApproxU2V2); // Build knots. Standard_Address ptrsvsurf = &myImpPrmSvSurfaces; buildKnots(theline, ptrsvsurf); if(myRelativeTol==Standard_False) { myComputeLine.Init(myDegMin, myDegMax, myTol3d*myData.myMinFactorXYZ, myTol2d*myData.myMinFactorUV, myNbIterMax, cut, myData.parametrization); myComputeLineBezier.Init(myDegMin, myDegMax, myTol3d*myData.myMinFactorXYZ, myTol2d*myData.myMinFactorUV, myNbIterMax, cut, myData.parametrization); } else { myComputeLine.Init(myDegMin, myDegMax, myTol3d, myTol2d, myNbIterMax, cut, myData.parametrization); myComputeLineBezier.Init(myDegMin, myDegMax, myTol3d, myTol2d, myNbIterMax, cut, myData.parametrization); } buildCurve(theline, ptrsvsurf); } //======================================================================= //function : NbMultiCurves //purpose : //======================================================================= Standard_Integer ApproxInt_Approx::NbMultiCurves() const { return 1; } //======================================================================= //function : UpdateTolReached //purpose : //======================================================================= void ApproxInt_Approx::UpdateTolReached() { if (myData.myBezierApprox) { Standard_Integer ICur; Standard_Integer NbCurves = myComputeLineBezier.NbMultiCurves(); for (ICur = 1 ; ICur <= NbCurves ; ICur++) { Standard_Real Tol3D, Tol2D ; myComputeLineBezier.Error (ICur, Tol3D, Tol2D) ; myTolReached3d = Max(myTolReached3d, Tol3D); myTolReached2d = Max(myTolReached2d, Tol2D); } } else { myComputeLine.Error (myTolReached3d, myTolReached2d); } } //======================================================================= //function : TolReached3d //purpose : //======================================================================= Standard_Real ApproxInt_Approx::TolReached3d() const { Standard_Real TheTol3D = RatioTol * myTolReached3d ; if (myData.myMinFactorXYZ>1.5e-7) TheTol3D = TheTol3D / myData.myMinFactorXYZ; //cout << "Tol 3D: " << TheTol3D << endl; return TheTol3D ; } //======================================================================= //function : TolReached2d //purpose : //======================================================================= Standard_Real ApproxInt_Approx::TolReached2d() const { Standard_Real TheTol2D = RatioTol * myTolReached2d ; if (myData.myMinFactorUV>1.5e-7) TheTol2D = TheTol2D / myData.myMinFactorUV; //cout << "Tol 2D: " << TheTol2D << endl; return TheTol2D ; } //======================================================================= //function : IsDone //purpose : //======================================================================= Standard_Boolean ApproxInt_Approx::IsDone() const { if(myData.myBezierApprox) { return(myComputeLineBezier.NbMultiCurves() > 0); //-- Lorsque la tolerance n est pas atteinte et qu il //-- faudrait rajouter des points sur la ligne //-- les approx sortent avec la meilleure tolerance //-- atteinte. ( Pas de rajout de points ds cette version) //-- return(myTolReached); } else { return(myComputeLine.IsToleranceReached()); } } //======================================================================= //function : Value //purpose : //======================================================================= const AppParCurves_MultiBSpCurve& ApproxInt_Approx::Value(const Standard_Integer ) const { if(myData.myBezierApprox) { return(myBezToBSpl.Value()); } else { return(myComputeLine.Value()); } } //======================================================================= //function : fillData //purpose : Fill ApproxInt data structure. //======================================================================= void ApproxInt_Approx::fillData(const Handle(TheWLine)& theline, const Standard_Boolean ApproxXYZ, const Standard_Boolean ApproxU1V1, const Standard_Boolean ApproxU2V2) { if(ApproxXYZ) { ComputeTrsf3d(theline, myData.Xo, myData.Ax, myData.Yo, myData.Ay, myData.Zo, myData.Az); } else { myData.Xo = myData.Yo = myData.Zo = 0.0; myData.Ax = myData.Ay = myData.Az = 1.0; } if(ApproxU1V1) { ComputeTrsf2d(theline, myData.U1o, myData.A1u, myData.V1o, myData.A1v,Standard_True, myUVRes1); } else { myData.U1o = myData.V1o = 0.0; myData.A1u = myData.A1v = 1.0; } if(ApproxU2V2) { ComputeTrsf2d(theline, myData.U2o, myData.A2u, myData.V2o, myData.A2v, Standard_False, myUVRes2); } else { myData.U2o = myData.V2o = 0.0; myData.A2u = myData.A2v = 1.0; } Standard_Real A3d = MINABS3(myData.Ax, myData.Ay, myData.Az); if((A3d < myData.myMinFactorXYZ) || (myData.myMinFactorXYZ == 0.0)) { myData.myMinFactorXYZ = A3d; } Standard_Real A2d = MINABS4(myData.A1u, myData.A1v, myData.A2u, myData.A2v); if((A2d < myData.myMinFactorUV) || (myData.myMinFactorUV == 0.0)) { myData.myMinFactorUV = A2d; } } //======================================================================= //function : prepareDS //purpose : //======================================================================= void ApproxInt_Approx::prepareDS(const Standard_Boolean theApproxXYZ, const Standard_Boolean theApproxU1V1, const Standard_Boolean theApproxU2V2, const Standard_Integer theIndicemin, const Standard_Integer theIndicemax) { myData.myMinFactorXYZ = 0.0; myData.myMinFactorUV = 0.0; myTolReached3d = myTolReached2d = 0.0; myUVRes1 = myUVRes2 = 1.0; myData.ApproxU1V1 = theApproxU1V1; myData.ApproxU2V2 = theApproxU2V2; myData.ApproxXYZ = theApproxXYZ; myData.indicemin = theIndicemin; myData.indicemax = theIndicemax; myData.nbpntmax = myNbPntMax; Approx_ParametrizationType parametrization; myComputeLineBezier.Parametrization(parametrization); myData.parametrization = parametrization; } //======================================================================= //function : buildKnots //purpose : //======================================================================= void ApproxInt_Approx::buildKnots(const Handle(TheWLine)& theline, const Standard_Address thePtrSVSurf) { myKnots.Clear(); if(myData.myBezierApprox) { ApproxInt_TheMultiLine aTestLine(theline, thePtrSVSurf, ((myData.ApproxXYZ)? 1 : 0), ((myData.ApproxU1V1)? 1: 0) + ((myData.ApproxU2V2)? 1: 0), myData.Xo, myData.Ax, myData.Yo, myData.Ay, myData.Zo, myData.Az, myData.U1o, myData.A1u, myData.V1o, myData.A1v, myData.U2o, myData.A2u, myData.V2o ,myData.A2v, myData.ApproxU1V1, myData.indicemin, myData.indicemax); Standard_Integer nbp3d = aTestLine.NbP3d(); Standard_Integer nbp2d = aTestLine.NbP2d(); TColgp_Array1OfPnt aTabPnt3d(1, Max(1, nbp3d)); TColgp_Array1OfPnt2d aTabPnt2d(1, Max(1, nbp2d)); TColgp_Array1OfPnt aPntXYZ(myData.indicemin, myData.indicemax); TColgp_Array1OfPnt2d aPntU1V1(myData.indicemin, myData.indicemax); TColgp_Array1OfPnt2d aPntU2V2(myData.indicemin, myData.indicemax); Standard_Integer i; for(i = myData.indicemin; i <= myData.indicemax; ++i) { if (nbp3d != 0 && nbp2d != 0) aTestLine.Value(i, aTabPnt3d, aTabPnt2d); else if (nbp2d != 0) aTestLine.Value(i, aTabPnt2d); else if (nbp3d != 0) aTestLine.Value(i, aTabPnt3d); // if(nbp3d > 0) { aPntXYZ(i) = aTabPnt3d(1); } if(nbp2d > 1) { aPntU1V1(i) = aTabPnt2d(1); aPntU2V2(i) = aTabPnt2d(2); } else if(nbp2d > 0) { if(myData.ApproxU1V1) { aPntU1V1(i) = aTabPnt2d(1); } else { aPntU2V2(i) = aTabPnt2d(1); } } } Standard_Integer aMinNbPnts = myData.nbpntmax; // Expected parametrization. math_Vector aPars(myData.indicemin, myData.indicemax); Parameters(aTestLine, myData.indicemin, myData.indicemax, myData.parametrization, aPars); ApproxInt_KnotTools::BuildKnots(aPntXYZ, aPntU1V1, aPntU2V2, aPars, myData.ApproxXYZ, myData.ApproxU1V1, myData.ApproxU2V2, aMinNbPnts, myKnots); } else { myKnots.Append(myData.indicemin); myKnots.Append(myData.indicemax); } } //======================================================================= //function : buildCurve //purpose : //======================================================================= void ApproxInt_Approx::buildCurve(const Handle(TheWLine)& theline, const Standard_Address thePtrSVSurf) { if(myData.myBezierApprox) { myBezToBSpl.Reset(); } Standard_Integer kind = myKnots.Lower(); Standard_Integer imin, imax; myTolReached = Standard_True; Standard_Boolean OtherInter = Standard_False; do { // Base cycle: iterate over knots. imin = myKnots(kind); imax = myKnots(kind+1); ApproxInt_TheMultiLine myMultiLine(theline, thePtrSVSurf, ((myData.ApproxXYZ)? 1 : 0), ((myData.ApproxU1V1)? 1: 0) + ((myData.ApproxU2V2)? 1: 0), myData.Xo, myData.Ax, myData.Yo,myData.Ay, myData.Zo,myData.Az, myData.U1o, myData.A1u, myData.V1o, myData.A1v, myData.U2o, myData.A2u, myData.V2o, myData.A2v, myData.ApproxU1V1, imin, imax); if(myData.myBezierApprox) { myComputeLineBezier.Perform(myMultiLine); if (myComputeLineBezier.NbMultiCurves() == 0) return; myTolReached&=myComputeLineBezier.IsToleranceReached(); } else { myComputeLine.Perform(myMultiLine); } UpdateTolReached(); Standard_Integer indice3d,indice2d1,indice2d2; indice3d = 1; indice2d1= 2; indice2d2= 3; if(!myData.ApproxXYZ) { indice2d1--; indice2d2--; } if(!myData.ApproxU1V1) { indice2d2--; } if(myData.ApproxXYZ) { Standard_Real ax,bx,ay,by,az,bz; ax = 1.0/myData.Ax; bx = -myData.Xo*ax; ay = 1.0/myData.Ay; by = -myData.Yo*ay; az = 1.0/myData.Az; bz = -myData.Zo*az; if(myData.myBezierApprox) { for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { myComputeLineBezier.ChangeValue(nbmc).Transform(indice3d,bx,ax,by,ay,bz,az); } } else { myComputeLine.ChangeValue().Transform(indice3d,bx,ax,by,ay,bz,az); } } if(myData.ApproxU1V1) { Standard_Real ax,bx,ay,by; ax = 1.0/myData.A1u; bx = -myData.U1o*ax; ay = 1.0/myData.A1v; by = -myData.V1o*ay; if(myData.myBezierApprox) { for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d1,bx,ax,by,ay); } } else { myComputeLine.ChangeValue().Transform2d(indice2d1,bx,ax,by,ay); } } if(myData.ApproxU2V2) { Standard_Real ax,bx,ay,by; ax = 1.0/myData.A2u; bx = -myData.U2o*ax; ay = 1.0/myData.A2v; by = -myData.V2o*ay; if(myData.myBezierApprox) { for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d2,bx,ax,by,ay); } } else { myComputeLine.ChangeValue().Transform2d(indice2d2,bx,ax,by,ay); } } OtherInter = Standard_False; if(myData.myBezierApprox) { for(Standard_Integer nbmc = 1; nbmc <= myComputeLineBezier.NbMultiCurves(); nbmc++) { myBezToBSpl.Append(myComputeLineBezier.Value(nbmc)); } kind++; if(kind < myKnots.Upper()) { OtherInter = Standard_True; } } } while(OtherInter); if(myData.myBezierApprox) { myBezToBSpl.Perform(); } }