トップページ > 空即是色 > 2006年の記事 > 2次ベジェ曲線
空即是色 2次ベジェ曲線
2006年 02月23日
赤い点が曲線のアンカーポイントです。
以下、ソースコード。
始点と終点の処理など色々特殊かもしれない。
太字の部分が2次ベジェ曲線の公式にあたる。

vpx: アンカーポイントの配列[x座標]
vpy: アンカーポイントの配列[y座標]
vp_size: vpx,vpyのサイズ
vp_div: 曲線の近似/分割数
bcpx: 算出した値が入る[x座標]
bcpy: 算出した値が入る[y座標]
void convertBezierCurve(
float* vpx,
float* vpy,
int vp_size,
int vp_div,
float* bcpx, // (vp_size-2)*vp_div+1
float* bcpy
){
float px1, py1, px2, py2, px3, py3;
float x, y;
float t, dt;
int idx;
// convert bezier curve
for( int i = 0; i < vp_size-2; i++ ){
// first
if( i == 0 ){
px1 = vpx[i];
py1 = vpy[i];
px2 = vpx[i+1];
py2 = vpy[i+1];
px3 = ( vpx[i+1] + vpx[i+2] ) / 2.0;
py3 = ( vpy[i+1] + vpy[i+2] ) / 2.0;
}
// end
else if ( i == vp_size-3 ){
px1 = ( vpx[i] + vpx[i+1] ) / 2.0;
py1 = ( vpy[i] + vpy[i+1] ) / 2.0;
px2 = vpx[i+1];
py2 = vpy[i+1];
px3 = vpx[i+2];
py3 = vpy[i+2];
}
else {
px1 = ( vpx[i] + vpx[i+1] ) / 2.0;
py1 = ( vpy[i] + vpy[i+1] ) / 2.0;
px2 = vpx[i+1];
py2 = vpy[i+1];
px3 = ( vpx[i+1] + vpx[i+2] ) / 2.0;
py3 = ( vpy[i+1] + vpy[i+2] ) / 2.0;
}
t = 0.0;
dt = 1.0 / (float)vp_div;
for( int j = 0; j < vp_div; j++ ){
x = (1-t)*(1-t)*px1 + 2.0*t*(1-t)*px2 + t*t*px3;
y = (1-t)*(1-t)*py1 + 2.0*t*(1-t)*py2 + t*t*py3;
t += dt;
idx = j+i*vp_div;
bcpx[idx] = x;
bcpy[idx] = y;
}
}
// last
idx = (vp_size-2) * vp_div;
bcpx[idx] = vpx[vp_size-1];
bcpy[idx] = vpy[vp_size-1];
}
こんな感じで使う。
int vp_size = 5;
float vpx[] = { 10, 20, 30, 40, 50 };
float vpy[] = { 20, 60, 30, 120, 10 };
// alloc
int vp_div = 10;
int bc_size = (vp_size-2)*vp_div+1;
float* bcpx = new float[bc_size];
float* bcpy = new float[bc_size];
memset( bcpx, 0, sizeof(float)*bc_size );
memset( bcpy, 0, sizeof(float)*bc_size );
// convert bezir
convertBezierCurve( vpx, vpy, vp_size, vp_div, bcpx, bcpy );
// draw bezier line
glColor3f( 1.0, 1.0, 1.0 );
glBegin( GL_LINE_STRIP );
for( int i = 0; i < bc_size; i++ ){
glVertex2f( bcpx[i], bcpx[i] );
}
glEnd();
// free
delete bcpx;
delete bcpy;
参考:
ベジェ曲線の数学的関数
トラックバック
この記事のトラックバックURL:http://null-null.net/mt/mt-tb.cgi/417


