QtCharts_动态图QSplineSeries 绘制平滑曲线
得到曲线上的点,画出曲线,这是一个很常见的需求。画曲线嘛,当然难不住我们,用 QPainter::drawLine() 把曲线上的点连起来不就好了?So easy,轻轻松松搞定,开开心心的交任务去了。
正在聚精会神炒股的老板一瞅,气不打一处来:“你这画的是什么鬼,这个线直来直去的,太不专业了”,抬头指着屏幕上的炒股软件,瞅着迷离的眼神:“看看人家的这个曲线,就像少女的皮肤般那么的柔顺、平滑”,口气马上一百八十度大转弯:“在看看你的,像八十岁老头的那样全是褶皱!” 擦完脸上的口水,赶快想办法去吧。
创建平滑曲线,有很多种方式,可以使用现成的库,例如 QWT,QCustomPlot 等,也可以研究平滑曲线的理论,实现平滑曲线的插值函数。这里我们提供二个实现,利用 QPainterPath,根据曲线上的点创建平滑曲线,他们各有利弊,使用分三步:
|
|
最后画出来的曲线效果如下,这次应该不会被喷了吧:
Qt 中可以使用 QPainterPath::cubicTo()
函数实现绘制平滑曲线,绘制平滑曲线的关键是控制点的计算,sp
为线段的起始点,ep 为线段的终点,c1,c2 为贝塞尔曲线的控制点,其坐标计算如下
类 SmoothCurveGenerator1 使用上面的原理生成平滑曲线
|
|
|
|
接下来就介绍一下生成平滑曲线的具体使用方法,就是开头被喷的那个曲线图的平滑实现。
在 SmoothCurveWidget.ui 上如图放两个 QCheckBox,命名为 showKnotsCheckBox 和 showSmoothCurveCheckBox,QPushButton 用于点击重新生成曲线,ComboBox 用于选择生成曲线的算法:
下面是 SmoothCurveWidget.h, SmoothCurveWidget.cpp 和 main.cpp
|
|
|
|
|
|
为了让程序更具有普谝性,曲线上的点采用随机生成,所以每次生成的曲线是不一样的,选中 “Smooth Curve” 时显示为平滑曲线,没有选中则显示为非平滑的曲线。选中 “Show knots” 显示曲线上的点,反之则不显示。
如果仔细观察 SmoothCurveGenerator1 生成的平滑曲线,会发现平滑曲线段之间会有很多小段的抖动,下面提供另一个也是使用 QPainterPath 实现平滑曲线的方法,可以解决平滑曲线段之间的抖动问题,但是曲线段在比较陡时,曲线上的值可能会超出曲线原来值的范围,但是总体上看效果更好,改编自 http://www.codeproject.com/Articles/31859/Draw-a-Smooth-Curve-through-a-Set-of-D-Points-wit,核心是使用曲线上的点计算出贝塞尔曲线的两个控制点,然后使用贝塞尔曲线生成平滑曲线,很惭愧的是生成控制点的算法细节我没看懂,只不过是作了一次搬运工,把程序移植到了 Qt 上,有兴趣的话,请自行参考吧,不过即使没有理解控制点的生成算法也不影响使用。
|
|
|
|
相信还有其他用于生成平滑曲线的方法,甚至可以同时解决 SmoothCurveGenerator1 和 SmoothCurveGenerator2 的问题,这个需要大家继续深入的研究了。