样条曲线catmull rom转bezier

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;
for(int i = 1; i < cps.size(); i ++) { 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

你可能感兴趣的:(ROM)