Dam*_*bic 4 c++ qt qpainterpath
有没有办法通过QT中的一组点绘制一条平滑的线?点的数量和位置在运行时设置。
目前,我绘制了一个 QPainterPath,其中包含 lineTo 从点到点的移动,创建一条路径。我确实使用了渲染提示抗锯齿,但路径仍然是锯齿状的。
我见过 QSplineSeries 似乎提供了这种弯曲路径,但它在 Qt4.8 中不可用,这是我正在使用的 QT 版本。
经常建议的另一个选项是使用贝塞尔曲线,但那些使用一个起点和终点以及两个控制点,所以我需要为每个线段(每条线)计算它,并以某种方式计算那些我没有的控制点在这一刻。
最后,我实现了某种解决方法,它基本上采用两条连接线,删除它们之间的连接点并将其替换为曲线。因为我有很多小线,这样的变化是不可见的,所以我删除了所有非常短的线并重新连接开放端。该功能主要由 Bojan Kverh 提供,查看他的教程:https ://www.toptal.com/c-plus-plus/rounded-corners-bezier-curves-qpainter
这里的功能:
namespace
{
float distance(const QPointF& pt1, const QPointF& pt2)
{
float hd = (pt1.x() - pt2.x()) * (pt1.x() - pt2.x());
float vd = (pt1.y() - pt2.y()) * (pt1.y() - pt2.y());
return std::sqrt(hd + vd);
}
QPointF getLineStart(const QPointF& pt1, const QPointF& pt2)
{
QPointF pt;
float rat = 10.0 / distance(pt1, pt2);
if (rat > 0.5) {
rat = 0.5;
}
pt.setX((1.0 - rat) * pt1.x() + rat * pt2.x());
pt.setY((1.0 - rat) * pt1.y() + rat * pt2.y());
return pt;
}
QPointF getLineEnd(const QPointF& pt1, const QPointF& pt2)
{
QPointF pt;
float rat = 10.0 / distance(pt1, pt2);
if (rat > 0.5) {
rat = 0.5;
}
pt.setX(rat * pt1.x() + (1.0 - rat)*pt2.x());
pt.setY(rat * pt1.y() + (1.0 - rat)*pt2.y());
return pt;
}
}
void PainterPath::smoothOut(const float& factor)
{
QList<QPointF> points;
QPointF p;
for (int i = 0; i < mPath->elementCount() - 1; i++) {
p = QPointF(mPath->elementAt(i).x, mPath->elementAt(i).y);
// Except for first and last points, check what the distance between two
// points is and if its less then min, don't add them to the list.
if (points.count() > 1 && (i < mPath->elementCount() - 2) && (distance(points.last(), p) < factor)) {
continue;
}
points.append(p);
}
// Don't proceed if we only have 3 or less points.
if (points.count() < 3) {
return;
}
QPointF pt1;
QPointF pt2;
QPainterPath* path = new QPainterPath();
for (int i = 0; i < points.count() - 1; i++) {
pt1 = getLineStart(points[i], points[i + 1]);
if (i == 0) {
path->moveTo(pt1);
} else {
path->quadTo(points[i], pt1);
}
pt2 = getLineEnd(points[i], points[i + 1]);
path->lineTo(pt2);
}
delete mPath;
mPath = path;
prepareGeometryChange();
}
Run Code Online (Sandbox Code Playgroud)