Qt5与现代OpenGL学习(八)在Widget里绘制曲面

请添加图片描述
surfacewidget.h

#ifndef SURFACEWIDGET_H
#define SURFACEWIDGET_H

#include <QWidget>
#include <QPainter>
#include <QMouseEvent>
#include <QToolTip>
#include <QDebug>
#include <cmath>

class SurfaceWidget : public QWidget
{
    Q_OBJECT

public:
    explicit SurfaceWidget(QWidget *parent = nullptr);

protected:
    void paintEvent(QPaintEvent *event) override;

private:
    // 声明为const成员函数,因为不修改类成员
    double surfaceFunction(double x, double y) const;

    QTransform m_transform;
    double m_scale = 50.0;
    bool m_selectedPointValid = false;
    double m_selectedX = 0;
    double m_selectedY = 0;
};

#endif // SURFACEWIDGET_H

surfacewidget.cpp

#include "surfacewidget.h"

SurfaceWidget::SurfaceWidget(QWidget *parent) : QWidget(parent)
{
    setMouseTracking(true); // 启用鼠标移动跟踪
}

void SurfaceWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    int width = this->width();
    int height = this->height();

    // 设置坐标系:原点在中心,Y轴向上
    painter.translate(width/2, height/2);
    painter.scale(1, -1);

    // 保存变换矩阵用于鼠标坐标转换
    m_transform = painter.transform();

    // 绘制曲面网格
    int steps = 50;

    // 绘制水平线
    for (int i = -steps; i <= steps; ++i) {
        double x = i * m_scale / steps;

        QPainterPath path;
        bool first = true;

        for (int j = -steps; j <= steps; ++j) {
            double y = j * m_scale / steps;
            double z = surfaceFunction(x, y);

            QPointF point(x * m_scale, y * m_scale - z * m_scale/2);

            if (first) {
                path.moveTo(point);
                first = false;
            } else {
                path.lineTo(point);
            }
        }

        painter.setPen(QPen(Qt::blue, 1));
        painter.drawPath(path);
    }

    // 绘制垂直线
    for (int j = -steps; j <= steps; ++j) {
        double y = j * m_scale / steps;

        QPainterPath path;
        bool first = true;

        for (int i = -steps; i <= steps; ++i) {
            double x = i * m_scale / steps;
            double z = surfaceFunction(x, y);

            QPointF point(x * m_scale, y * m_scale - z * m_scale/2);

            if (first) {
                path.moveTo(point);
                first = false;
            } else {
                path.lineTo(point);
            }
        }

        painter.setPen(QPen(Qt::red, 1));
        painter.drawPath(path);
    }

    // 绘制选中的顶点
    if (m_selectedPointValid) {
        double z = surfaceFunction(m_selectedX, m_selectedY);
        QPointF point(m_selectedX * m_scale,
                     m_selectedY * m_scale - z * m_scale/2);

        painter.setPen(QPen(Qt::green, 4));
        painter.drawPoint(point);
    }
}

double SurfaceWidget::surfaceFunction(double x, double y)  const
{
    // 定义曲面函数 - 双曲抛物面
    return (x*x - y*y) / 100.0;

    // 可选其他曲面函数:
    // return 5 * sin(sqrt(x*x + y*y) / 2.0; // 正弦曲面
}

在mainwindow.ui中,添加QWidget,并提升为:SurfaceWidget

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向日葵xyz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值