Processing math: 100%

n차 Bezier 곡선을 기술하는 매개변수가 t일 때, 곡선을 [0,t]인 구간과 [t,1]인 두 구간으로 나누기 위해 필요한 control point을 구해보자.

// deg = Q.size()-1;
void BezierSubdivision(const int deg, const std::vector<CfPt>& Q, const double t, 
                       std::vector<CfPt>& Left,
                       std::vector<CfPt>& Right) {
    Left.resize(deg+1);	
    Right.resize(deg+1);
    std::vector<CfPt> Q1(deg+1);
    for (int i = 0; i <= deg; i++)/* copy of control points*/
        Q1[i] = Q[i];

    /* triangle computation	*/
    Left[0] = Q1[0];
    Right[deg] = Q1[deg];
    for (int i = 0; i < deg; i++) {
        for (int j = 0; j < (deg-i); j++)
            Q1[j] = Q1[j] * (1 - t) + Q1[j+1] * t;
        Left[i+1] = Q1[0];
        Right[deg-1-i] = Q1[deg-1-i]; 
    }
}
728x90

'Computational Geometry' 카테고리의 다른 글

Centripetal Catmull-Rom Spline  (0) 2024.06.06
Bezier curves  (1) 2024.04.19
Derivatives of Bezier Curves  (1) 2024.04.12
Least Squares Bezier Fit  (0) 2024.04.05
Why Cubic Splines?  (9) 2024.03.16
,

한 점에서 Bezier 곡선까지의 최단거리나, Bezier 곡선상의 한 지점에서 접선 또는 법선을 구하기 위해서는 도함수를 구해야 할 필요가 생긴다. 그런데 주어진 찻수에서 Bezier 곡선의 도함수는 한 찻수 낮은 Bezier 곡선으로 표현할 수 있어서 상대적으로 쉽게 계산할 수 있다. 찻수가 n인 Bezier 곡선이

B(t)=nk=0bk,n(t)Qk=nk=0n!k!(nk)!tk(1t)nkQk

로 표현되므로 이의 미분은 

dB(t)dt=nk=1n!(k1)!(nk)!tk1(1t)nkQk

       n1k=0n!k!(n1k)!tk(1t)n1kQk

=n1k=0(n1)!k!(n1k)!tk(1t)n1k(nQk+1nQk)

=n1k=0bk,n1(t)(nQk+1nQk)

따라서 n Bezier 곡선의 미분은 control 점이

˜Qk=n(Qk+1Qk)k=0,1,..,n1

로 주어지는 (n1)차 Bezier 곡선으로 표현된다. 미분을 

dB(t)dt=n[B1(t)B0(t)]

B1(t)=n1i=0bi,n1(t)Qi+1

B0(t)=n1i=0bi,n1(t)Qi처럼 분해를 하면 B1(t)는 컨트롤점이 {P1,P2,...,Pn}으로 구성된 (n1)차 Bezier 곡선이고, B0(t)는 컨트롤점이 {P0,P1,...,Pn1}으로 만들어지는 (n1)차 Bezier 곡선이다. 따라서 Casteljau 알고리즘을 이용하여 B1(t)B0(t)을 구하여 그 차이를 계산하면 미분값을 얻을 수 있다.

 

곡선의 curvature: https://kipl.tistory.com/105

 

 
// Bezier cureve evaluation at t;
// deg = the degree of the bezier curve;
double Bezier(int deg, double Q[], double t) {
    if (deg==0) return Q[0];
    else if (deg==1) return (1 - t) * Q[0] + t * Q[1];
    else if (deg==2) return (1-t)*((1-t)*Q[0] + t*Q[1]) + t*((1-t)*Q[1] + t*Q[2]);
    
    std::vector<double> Q1(deg + 1);
    for (int i = 0; i <= deg; i++)  Q1[i] = Q[i];
    // triangle computations;
    for (int k = 0; k < deg; k++)
        for (int j = 0; j < (deg - k); j++)
            Q1[j] = (1 - t) * Q1[j] + t * Q1[j + 1];
            
    return Q1[0];
 }
// derivative of a Bezier curve at t;
double BezierDerivative(int deg, double Q[], double t) {
    if (deg==0) return 0;
    else if (deg==1) return Q[1] - Q[0];
    else if (deg==2) return 2*((1-t)*(Q[1]-Q[0])+t*(Q[2]-Q[1]));
    
    std::vector<double> Q1(degree + 1);
    for (int i = 0; i <= deg; i++) Q1[i] = Q[i];
    // triangle computations;
    for (int k = 0; k < (deg - 1); k++)
        for (int j = 0; j < (deg - k); j++)
            Q1[j] = (1 - t) * Q1[j] + t * Q1[j + 1];
    
    return deg * (Q1[1] - Q1[0]);
};
// 2nd derivative of a Bezier curve at t;
double EvalBezier2ndDeriv(int deg, double Q[], double t) {
    if (2 > deg) return 0;
    std::vector<double> Q1(deg+1);
    for (int i = 0; i <= deg; i++) Q1[i] = Q[i];
    
    for (int i = 0; i < (deg-2); i++) 
        for (int j = 0; j < (deg-i); j++) 
            Q1[j] = (1-t)*Q1[j] + t*Q1[j+1];
    
    double v0 = 2*(Q1[1] - Q1[0]);
    double v1 = 2*(Q1[2] - Q1[1]);
    return v1 - v0;
}; 
// curvature of a Bezier curve at t;
double BezierCurvature(int deg, CfPt Q[], double t) {
    if (deg < 2) return 0;
    CfPt d1 = EvalBezierDeriv(deg, Q, t);
    CfPt d2 = EvalBezier2ndDeriv(deg, Q, t);
    double flen = hypot(d1.x, d1.y);
    return fabs(d1.x*d1.y - d2.x*d1.y)/ flen / flen / flen;
}
728x90

'Computational Geometry' 카테고리의 다른 글

Bezier curves  (1) 2024.04.19
Subdividing a Bezier Curve  (0) 2024.04.18
Least Squares Bezier Fit  (0) 2024.04.05
Why Cubic Splines?  (9) 2024.03.16
Natural Cubic Spline  (0) 2024.03.11
,

{Ck}=argmin(L)L=N1k=0|Pkni=0bi,n(tk)Ci|2

tk=dk/dN1,dk=dk1+|PkPk1|

Bernstein basis polynomial: bi,n(t)=(ni)ti(1t)ni=nj=0tjMji

Mji=n!(nj)!(1)j+ii!(ji)!=(1)j+iMjj(ji)(ji)

note:  Mjj=(nj),Mji=0(j<i)

// calculate binomial coefficients using Pascal's triangle
void binomialCoeffs(int n, double** C) {
    // binomial coefficients
    for (int i = 0; i <= n; i++)
        for (int j = 0; j <= i; j++)
            if (j == 0 || j == i) C[i][j] = 1;
            else                  C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
std::vector<double> basisMatrix(int degree) {
    const int n = degree + 1;
    std::vector<double* > C(n);
    std::vector<double> Cbuff(n*n);
    for (int i = n; i-->0;) 
        C[i] = &Cbuff[i * n];
    // C[degree, k]; k=0,..,degree)
    binomialCoeffs(degree, &C[0]);
    // seting the diagonal;
    std::vector<double> M(n * n, 0); // lower triangle; 
    for (int j = 0; j <= degree; j++)
        M[j * n + j] = C[degree][j];
    // compute the remainings;
    for (int i = 0; i <= degree; i++) 
        for (int j = i + 1; j <= degree; j++)
            M[j * n + i] = ((j + i) & 1 ? -1 : 1) * C[j][i] * M[j * n + j];
    return M;
}
728x90

'Computational Geometry' 카테고리의 다른 글

Subdividing a Bezier Curve  (0) 2024.04.18
Derivatives of Bezier Curves  (1) 2024.04.12
Why Cubic Splines?  (9) 2024.03.16
Natural Cubic Spline  (0) 2024.03.11
Approximate Distance Between Ellipse and Point  (0) 2024.03.08
,