b0,..,b3是贝塞尔,c-1, c2是catmull rom控制点
[b0] = 1 [ 0 6 0 0] [c_1] [b1] - [-1 6 1 0] [c0] [b2] 6 [ 0 1 6 -1] [c1] [b3] [ 0 0 6 0] [c2]
Qt版本代码:
QList<QPointF> cps; cps.append(QPointF(0, 100)); cps.append(QPointF(75, 75)); cps.append(QPointF(200, 150)); cps.append(QPointF(325, 25)); cps.append(QPointF(400, 100)); QPainter p(this); //draw control point foreach(const QPointF& pos, cps) p.drawEllipse(pos, 5, 5); QPainterPath path; //create bezier from catrull-rom /* full conversion matrix (inverse bezier * catmull-rom): 4*4(matrix, 4* 1(catrull-rom control points) 0.000, 1.000, 0.000, 0.000, -0.167, 1.000, 0.167, 0.000, 0.000, 0.167, 1.000, -0.167, 0.000, 0.000, 1.000, 0.000 conversion doesn't require full matrix multiplication, so below we simplify */
path.moveTo(cps.first());
QPointF prevFar, prev, point, next;
)
{
int prevFarIdx = i - 2;
int prevIdx = i - 1;
int nextIdx = i + 1;
point = cps[i];
if(prevIdx >= 0)
prev = cps[prevIdx];
else
prev = point;
if(prevFarIdx >= 0)
prevFar = cps[prevFarIdx];
else
prevFar = prev;
if(nextIdx < cps.size())
next = cps[nextIdx];
else
next = point;
QPointF control1(prevFar.x() * qreal(-0.167) +
prev.x() +
point.x() * qreal(0.167),
prevFar.y() * qreal(-0.167) +
prev.y() +
point.y() * qreal(0.167));
QPointF control2(prev.x() * qreal(0.167) +
point.x() +
next.x() * qreal(-0.167),
prev.y() * qreal(0.167) +
point.y() +
next.y() * qreal(-0.167));
path.cubicTo(control1, control2, point);
}
p.drawPath(path);
参考:
1. http://stackoverflow.com/questions/1030596/drawing-hermite-curves-in-opengl