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

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

로 표현되므로 이의 미분은 

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

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

=n1k=0(n1)!k!(n1k)!tk(1t)n1k(nQk+1nQk)=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
,