在QGraphicsView上实现交互式样条曲线的最佳方法是什么?
What's the best way to implement interactive spline-like curve on QGraphicsView?
我正在开发应用程序,该应用程序允许用户上传岩石裂缝的图像并将样条近似应用于该裂缝。
为此,我有QGraphicsView
,显示上传的图像。 上传图像后,用户可以选择在scene
上绘制点,我希望与线条一致地连接。这些连接的点将形成一条曲线,我想这是交互式的。通过交互式,我的意思是我希望用户能够在不破坏曲线的情况下拖动点,制作连接点的线,随点移动。我还想让用户能够删除选定的点,以便相邻的点保持连接。这些不是我想要的所有功能,但我想你明白了。
我所做的是我创建了一个类MeasurePoint
,它继承自QGraphicsItem
并包含有关一个点的所有信息。它具有以下字段:
int xPos;
int yPos;
int index;
bool movable;
bool selected;
该类还具有几种管理这些点的方法(字段的getter和setter函数等)。但是我没有在该类中实现连接功能,因为它只包含有关单个点的信息,而不是进一步的信息。我喜欢点的行为方式,如果我简单地将它们添加到场景中。但是现在我需要按照我之前描述的方式连接它们,但我真的不知道该怎么做。
存储积分的最佳方式是什么?我应该如何实现点之间的连接?任何可能的帮助将不胜感激。
附言如果这个问题需要我实现类MeasurePoint
,我会编辑它。
使用 QGraphicsPathItem 绘制样条曲线。然后,使用QPainterPath::cubicTo
方法在点之间创建连接。
您需要计算控制点以在两点之间绘制平滑的贝塞尔曲线。
你可以找到一堆基于二次贝塞尔曲线的更好的库,但下面的一个快速示例使用Qt类型和一种天真的方法来理解如何获取控制点:
QPair<QPointF, QPointF> controlPoints(QPointF const& p0, QPointF const& p1, QPointF const& p2, qreal t=0.25)
{
QPair<QPointF, QPointF> pair;
qreal d01 = qSqrt( ( p1.x() - p0.x() ) * ( p1.x() - p0.x() ) + ( p1.y() - p0.y() ) * ( p1.y() - p0.y() ) );
qreal d12 = qSqrt( ( p2.x() - p1.x() ) * ( p2.x() - p1.x() ) + ( p2.y() - p1.y() ) * ( p2.y() - p1.y() ) );
qreal fa = t * d01 / ( d01 + d12 );
qreal fb = t * d12 / ( d01 + d12 );
qreal c1x = p1.x() - fa * ( p2.x() - p0.x() );
qreal c1y = p1.y() - fa * ( p2.y() - p0.y() );
qreal c2x = p1.x() + fb * ( p2.x() - p0.x() );
qreal c2y = p1.y() + fb * ( p2.y() - p0.y() );
pair.first = QPointF( c1x, c1y );
pair.second = QPointF( c2x, c2y );
return pair;
}
然后,浏览您的积分列表以创建QPainterPath
:
QPainterPath BackgroundBuilder::buildPath(QList<QPointF> const& points)
{
QPainterPath pth;
QPair<QPointF, QPointF> pair = controlPoints(points.at(0), points.at(1), points.at(2));
QPointF p0 = pair.second;
pth.moveTo(0, 0);
pth.lineTo(p0);
for (int i = 2; i != points.count() - 1; ++i)
{
QPair<QPointF, QPointF> pair = controlPoints( points.at(i - 1), points.at(i), points.at(i + 1));
pth.cubicTo( p0, pair.first, points.at( i ) );
p0 = pair.second;
}
return pth;
}
您可能需要将MeasurePoint
转换为QPointF
以保持此代码泛型:
QList<QPointF> points;
QList<MeasurePoint*> measures = ...;
for (MeasurePoint* measure: measures)
{
points << QPointF(measure.xPos, measure.yPos);
}
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 在C++中向零方向近似的最佳方法
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 检测win32服务创建和删除的最佳方法
- 在C++中样板"冷/never_inline"错误处理技术的最佳方法是什么?
- 在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?
- 将线程中的数据存储到全局容器的最佳方法?
- 将一系列整数放入类的最佳方法是什么?
- 在派生类中使用基类的私有成员变量的最佳方法
- 在 C++ 中将非指定类型作为参数传递的最佳方法?
- Qt - QVector 和模型视图 - 从列表视图获取自定义类的最佳方法是什么?
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- 比较两个节点坐标的最佳方法是什么?
- 在nodejs中使用本机代码的最佳方法是什么?
- 将 pybind11 绑定标记为已弃用的最佳方法
- C++:将向量传递到构造函数以创建成员变量的最佳方法?
- C++中变量混叠的最佳方法
- 读取大文件(>2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是什么?