样条曲线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

转载于:https://www.cnblogs.com/yanhuiw/p/4385685.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值