如何从曲线中获取贝塞尔点

How to get Bezier points from a curve

提问人:Summit 提问时间:11/13/2023 最后编辑:Summit 更新时间:11/14/2023 访问量:57

问:

我正在使用内置的Qt函数在Qt中绘制贝塞尔曲线:

void OpacityCurveWidget::paintEvent(QPaintEvent* event) {
    QPainter painter(this);
    painter.fillRect(0, 0, width(), height(), Qt::white);

    painter.setPen(Qt::blue);
    QPainterPath path;
    glm::vec2 startPoint(0, (1.0 - opacityCurve[0].opacity) * height()); // Invert y-coordinate
    path.moveTo(startPoint.x, startPoint.y);

    for (size_t i = 1; i < opacityCurve.size(); ++i) {
        int x1 = static_cast<int>(opacityCurve[i - 1].position.x * width());
        int x2 = static_cast<int>(opacityCurve[i].position.x * width());
        int y1 = static_cast<int>((1.0 - opacityCurve[i - 1].position.y) * height()); // Invert y-coordinate
        int y2 = static_cast<int>((1.0 - opacityCurve[i].position.y) * height());     // Invert y-coordinate
        int cx1 = static_cast<int>(opacityCurve[i - 1].handle2.x * width());
        int cy1 = static_cast<int>((1.0 - opacityCurve[i - 1].handle2.y) * height()); // Invert y-coordinate
        int cx2 = static_cast<int>(opacityCurve[i].handle1.x * width());
        int cy2 = static_cast<int>((1.0 - opacityCurve[i].handle1.y) * height()); // Invert y-coordinate

        QPointF startPointF(startPoint.x, startPoint.y);
        QPointF controlPoint1F(cx1, cy1);
        QPointF controlPoint2F(cx2, cy2);
        QPointF endPointF(x2, y2);
        path.cubicTo(controlPoint1F, controlPoint2F, endPointF);

绘制它们后,我能够移动点,它们的手柄将新点和手柄 (x,y) 位置数据保存到矢量中。

根据这些数据,我尝试在给定的 x 位置处获得曲线 y 位置:

float OpacityCurveWidget::getYPositionAtX(float x) const {
    if (opacityCurve.size() < 2) {
        return 0.0f;
    }

    // Find the segment of the Bezier curve that contains the given x-coordinate
    size_t segmentIndex = 0;
    while (segmentIndex < opacityCurve.size() - 1 && x > opacityCurve[segmentIndex + 1].position.x) {
        segmentIndex++;
    }

   
    // Calculate t, the parameter for the cubic Bezier curve formula
    float t = (x - opacityCurve[segmentIndex].position.x) /
        (opacityCurve[segmentIndex + 1].position.x - opacityCurve[segmentIndex].position.x);

    // Use the cubic Bezier formula to calculate the y-coordinate
    float y = (1 - t) * (1 - t) * (1 - t) * opacityCurve[segmentIndex].position.y +
        3 * (1 - t) * (1 - t) * t * opacityCurve[segmentIndex].handle2.y +
        3 * (1 - t) * t * t * opacityCurve[segmentIndex + 1].handle1.y +
        t * t * t * opacityCurve[segmentIndex + 1].position.y;

    // Invert the y-coordinate
    y = 1.0f - y;

    // Return the y-coordinate without multiplying by height
    return y;
}

我面临的问题是,当我移动曲线点手柄的 x 位置时,这也会影响 Qt 图中曲线点的 y 位置,但在我的计算中,仅在 x 方向上移动任何手柄点不会影响点的 y 位置。

这就是QT曲线。enter image description here

当我在 x 方向上移动任何手柄时,它也会影响曲线点的 y 位置。enter image description here

当总 X 长度为 0.5 - 0 时,如何计算 X 1.0 处的 Y 位置?

qt math qpainter cubic-bezier qpainterpath

评论

1赞 Mike 'Pomax' Kamermans 11/14/2023
如果“当我移动曲线点手柄的 x 位置时,也会影响 Qt 图中曲线点的 y 位置”是您要解决的问题,请重写您帖子的代码,使其成为显示关闭的最小可重现示例。目前,您的帖子没有一个独立的示例来展示问题。
0赞 Summit 11/14/2023
@Mike'Pomax'Kamermans 我的 QT 曲线很好,但是当我使用相同的点进行计算时,我编写的函数不会考虑当我仅在 x 位置移动手柄时曲线点的 y 位置的变化。
0赞 Summit 11/14/2023
@Mike'Pomax'Kamermans,我在问题中添加了更多细节,请看一下。
0赞 Summit 11/14/2023
@Mike'Pomax'Kamermans 我编写的 Bezeir Y Position 函数(getYPositionAtX())没有考虑句柄的 X 位置变化。
0赞 Mike 'Pomax' Kamermans 11/14/2023
不过,从字面上看,这就是贝塞尔曲线应该表现的方式。曲线锚定在起点和终点处,曲线的起点和终点切线“指向”控制点。如果移动控制点,则整个曲线(起点和终点除外,它们是固定的)会改变形状。如果你想计算给定一些,这已经被几个帖子所涵盖,比如三次贝塞尔曲线 - 得到给定 X 的 Y,并在三次贝塞尔曲线上找到给定 X 的 Yyx

答: 暂无答案