绘制渐变的贝塞尔曲线

原创

前面介绍了使用Qt中的API绘制贝塞尔曲线,使用Qt的API绘制贝塞尔曲线可参见绘制贝塞尔曲线,本章介绍一下使用线段连接的方式绘制一条渐变的贝塞尔曲线。
效果如下图所示:

二阶贝塞尔曲线的公式如下:
B(t)=P0(1−t)3+3P1t(1−t)2+3P2t2(1−t)+P3t3,t∈[0,1]

P0为起始点的坐标,P3为终点的坐标,P1和P2为控制点的坐标。t在0-1之间取值,B(t)为计算的曲线坐标点。

完整的程序代码如下,本例子中取100个样点进行绘制:
头文件

#include <QWidget>

class BezierCurve : public QWidget
{
    Q_OBJECT

public:
    BezierCurve(QWidget *parent = nullptr);
    ~BezierCurve();

protected:
    void paintEvent(QPaintEvent *event) override;

private:
    int m_SampleCount;

    // 绘制贝塞尔曲线
    void drawBezierCurve(QPainter* painter, QPointF startPos, QPointF c1, QPointF c2, QPointF endPos);
    // 获取渐变的颜色
    QColor getGradientColor(int index);

    QColor m_StartColor;    // 起始颜色
    QColor m_EndColor;      // 结束颜色
};

源文件

#include "BezierCurve.h"
#include <QPainter>
#include <QVBoxLayout>
#include <QColor>
#include <QApplication>
#include <QStyleOption>

BezierCurve::BezierCurve(QWidget *parent)
    :QWidget(parent)
{
    m_SampleCount = 100;

    m_StartColor = QColor(255, 255, 0);
    m_EndColor = QColor(0, 255, 255);

    this->setProperty("NormalWidget", "NormalWidget");
}

BezierCurve::~BezierCurve()
{

}

void BezierCurve::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    // 绘制样式
    QStyleOption opt;
    opt.init(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);

    painter.setRenderHint(QPainter::Antialiasing, true);

    // 绘制贝塞尔曲线
    drawBezierCurve(&painter, QPointF(20, 20), QPointF(20, 500), QPointF(500, 20), QPointF(500, 500));
    return QWidget::paintEvent(event);
}

void BezierCurve::drawBezierCurve(QPainter* painter, QPointF startPos, QPointF c1, QPointF c2, QPointF endPos)
{
    painter->save();

    QPointF tempPos = startPos;
    for (int i=0; i<=m_SampleCount; ++i)
    {
        // 设置画笔
        QPen pen;
        QColor lineColor = getGradientColor(i);
        pen.setColor(lineColor);
        pen.setWidth(3);
        painter->setPen(pen);

        qreal t = i * 1.0 / m_SampleCount;
        QPointF pos = pow((1 - t), 3) * startPos + \
                      3 * t * pow((1 - t), 2) * c1 + \
                      3 * t * t * (1 - t) * c2 + \
                      pow(t, 3) * endPos;

        // 绘制贝塞尔曲线
        painter->drawLine(tempPos, pos);
        tempPos = pos;
    }

    painter->restore();
}

QColor BezierCurve::getGradientColor(int index)
{
    qreal redInterval = (m_EndColor.red() - m_StartColor.red()) * 1.0 / m_SampleCount;
    qreal greenInterval = (m_EndColor.green() - m_StartColor.green()) * 1.0 / m_SampleCount;
    qreal blueInterval = (m_EndColor.blue() - m_StartColor.blue()) * 1.0 / m_SampleCount;

    QColor gradientColor;
    gradientColor.setRed(redInterval * index + m_StartColor.red());
    gradientColor.setGreen(greenInterval * index + m_StartColor.green());
    gradientColor.setBlue(blueInterval * index + m_StartColor.blue());

    return gradientColor;
}
不会飞的纸飞机
扫一扫二维码,了解我的更多动态。

下一篇文章:Qt渐变方式显示图片