已知24个点,求期间任意几个点的值(贝赛尔曲线)
已经知道24个小时对应的24个点的具体数值,如 13:00对应192; 14:00对应132也就是说现在可以利用这24个数据画出来一条曲线(好像就是贝赛尔曲线的算法),那么下面有2个问题
1 贝赛尔曲线的算法具体怎么写呢?把这24个点或者几个点的值作为参数传进去,得到这条曲线
2 想得到0:00~23:59 一共1440分钟的,每一分钟的值,怎么计算?给24个值 或者说给几个值,得到
这些值中间的点值,具体说,比如给了3点和4点的2个值作为参数,如何能得到3:01~3:59 这59个值呢?
期待解答,万分感谢,
boss给了一个c++写的例子,没看懂,一起发出来期待帮忙解答
モデラーカーブの計算方法
モデラーで使用されているカーブは、Catmull-Rom 曲線を基本にした3次曲線です。
基本的なパラメトリックな3次曲線は、下記のように定義することができます。
p(t) = h1 * p1 + h2 * p2 + h3 * r1 + h4 * r2
p1 と p2 は、曲線スパン端点の制御点です。
r1 と r2 はそれぞれの接線ベクトルであり、h1 と h2 は、Hermite係数です。
t2 = t * t
t3 = t2 * t
h2 = 3.0f * t2 - t3 - t3
h1 = 1.0f - h2
h4 = t3 - t2
h3 = h4 - t2 + t
Catmull-Rom 曲線の接線ベクトルは、下記のように計算します。
r1 = (p2 - p0) / 2
r2 = (p3 - p1) / 2
p0 と p3 は、それぞれ p1, p2 側のポイントです。
制御点が極端に不均衡な位置にあった場合、問題が発生します。 曲線のループを構成する短いセグメントが制御点を飛び越えてしまいます。 安定的なカーブを作成し、操作上問題のない動きをさせるために、モデラーは 各ポイントにおいて入ベクトルと出ベクトルの重み付けをした平均値で接線 ベクトルを見つけています。
v1 = p1 - p0
v2 = p2 - p1
v3 = p3 - p2
r1 = (v1 * |v2| + v2 * |v1|) / (|v1| + |v2|)
r2 = (v2 * |v3| + v3 * |v2|) / (|v2| + |v3|)
|v1| は、v1 の長さです。v2, v3 も同様です。
次にp0 と p3が存在しない場合の処理も考える必要があります。 この問題は、最初の点もしくは最後の点が連続点(EDPF_CCSTARTもしくはEDPF_CCENDがカーブにセットされていない)が存在しない場合に起こります。モデラーは最初の点の前もしくは最後の点の後に仮想の点を作成する必要があります。
この仮想の点を作成するために、近傍の3つの点を使用します。
q = q2 + 3 (q0 - q1)
この式は曲線の始点、終点のどちらにも適用します。 q0 は、第1ポイント(最終ポイント)であり、q は、任意の近傍点になります。
上記の計算方法を使用して、ポイント座標値と対応する接線ベクトルの配列を作成するコードを以下に示します。
EDPolygonInfo *pol;
EDPointInfo *pnt;
LWDVector *pos, *tangent, v1, v2;
int i, j, npoints, ccstart, ccend;
double vlen1, vlen2;
ccstart = ( pol->flags & EDPF_CCSTART ) != 0;
ccend = ( pol->flags & EDPF_CCEND ) != 0;
npoints = pol->numPnts + 2 - ( ccstart + ccend );
pos = calloc( npoints, sizeof( LWDVector ));
tangent = calloc( npoints, sizeof( LWDVector ));
for( i = 0; i < pol->numPnts; i++ ) {
pnt = edit->pointInfo( edit->state, pol->points[ i ] );
for( j = 0; j < 3; j++ )
pos[ i + !ccstart ][ j ] = pnt->position[ j ] ;
}
if ( !ccstart )
for ( j = 0; j < 3; j++ )
pos[ 0 ][ j ] = pos[ 3 ][ j ]
+ 3 * ( pos[ 1 ][ j ] - pos[ 2 ][ j ] );
if ( !ccend )
for ( j = 0; j < 3; j++ )
pos[ npoints - 1 ][ j ] = pos[ npoints - 4 ][ j ]
+ 3 * ( pos[ npoints - 2 ][ j ] - pos[ npoints - 3 ][ j ] );
for ( i = 1; i < npoints - 1; i++ ) {
vlen1 = vlen2 = 0;
for ( j = 0; j < 3; j++ ) {
v1[ j ] = pos[ i ][ j ] - pos[ i - 1 ][ j ];
v2[ j ] = pos[ i + 1 ][ j ] - pos[ i ][ j ];
vlen1 += v1[ j ] * v1[ j ];
vlen2 += v2[ j ] * v2[ j ];
}
vlen1 = sqrt( vlen1 );
vlen2 = sqrt( vlen2 );
if ( vlen1 == 0.0 || vlen2 == 0.0 )
for ( j = 0; j < 3; j++ )
tangent[ i ][ j ] = 0.0;
else
for ( j = 0; j < 3; j++ )
tangent[ i ][ j ] = ( v1[ j ] * vlen2 + v2[ j ] * vlen1 )
/ ( vlen1 + vlen2 );
}
0 < i < npoints - 1 において pos[ i ] と pos[ i + 1 ] 間の任意のポイント p(t) は、 次のコードで求めることができます。
hermite( t, &h1, &h2, &h3, &h4 );
for ( j = 0; j < 3; j++ )
pos[ j ] = h1 * pos[ i ][ j ]
+ h2 * pos[ i + 1 ][ j ]
+ h3 * tangent[ i ][ j ]
+ h4 * tangent[ i + 1 ][ j ];
void hermite( float t, float *h1, float *h2, float *h3, float *h4 )
{
float t2, t3;
t2 = t * t;
t3 = t * t2;
*h2 = 3.0f * t2 - t3 - t3;
*h1 = 1.0f - *h2;
*h4 = t3 - t2;
*h3 = *h4 - t2 + t;
}
补充:VB , 基础类