Si el artículo es un artículo original, indique la fuente del artículo original al reproducirlo.
La dirección del blog de este artículo: https://hpzwl.blog.csdn.net/article/details/130264470
Estimados lectores, el conocimiento es infinito pero la mano de obra es limitada. Puede cambiar sus necesidades, encontrar profesionales o hacer su propia investigación.
Columna de desarrollo de Qt: tecnología de desarrollo (haga clic en el portal)
Anterior: " Tecnología de desarrollo de Qt: Notas de desarrollo de gráficos Q3D (2): Introducción al histograma 3D de Q3DBar, demostración y explicación detallada del código "
Siguiente: Estén atentos...
prefacio
qt proporciona q3d para el desarrollo 3D. Aunque este marco no ha sido ampliamente utilizado y no tiene tanto éxito, y su rendimiento también es muy deficiente, la visualización de aplicaciones ordinarias punto a punto aún es posible.
Entre ellos se encuentran magníficos gráficos tridimensionales, que se pueden usar cuando la cantidad de datos no es grande.
El histograma y el gráfico de dispersión q3d básicos se introdujeron anteriormente, y este artículo presenta el gráfico de superficie tridimensional básico.
Demostración: efecto de demostración de diagrama de dispersión de Q3DSurface
enlace de descarga:
Dirección de descarga del paquete de ejecución de demostración: https://download.csdn.net/download/qq21497936/87708061
Descarga del grupo QQ: haga clic en el avatar principal del blog para ingresar a la página de inicio del blog, verifique el lado derecho, allí está el información de contacto del grupo QQ (haga clic en " Archivo " Buscar " q3d ", el grupo y las publicaciones del blog se actualizarán simultáneamente)
Dirección de descarga de Baidu Netdisk: https://pan.baidu.com/s/1bWNR5E6Y9utu8iey9rIu0g?pwd=1234
Gráfico 3D proporcionado por Q3D
Depende de QtDataVisualization. Al instalar qt, elija instalar el módulo QtDataVisualization.
Diagrama de dispersión Q3DScatter
El rendimiento del gráfico de dispersión Q3D admite alrededor de 1000 puntos sin demora. Depende de la PC. ¿Cuál es el concepto de 1000 puntos? Se puede entender como: área de 10x10x10, un punto de datos para cada área.
Histograma Q3DBars
El histograma de Q3D es similar al gráfico de dispersión en rendimiento.
Q3DMapa de relieve de plano de superficie, mapa de textura de plano, mapa de curva de plano
El histograma de Q3D es similar al gráfico de dispersión en rendimiento.
Q3DCurva del plano de superficie
Introducción
La clase Q3DSurface proporciona métodos para renderizar imágenes de superficie 3D. Esta clase permite a los desarrolladores renderizar mapas de superficie 3D y verlos girando libremente la escena. Las propiedades visuales de las superficies, como los modos de dibujo y el sombreado, se pueden controlar a través de QSurface3DSeries.
Q3DSurface admite la selección al mostrar esferas resaltadas en puntos de datos en los que el usuario hace clic con el botón izquierdo del mouse (cuando se usa el controlador de entrada predeterminado) o mediante la selección a través de QSurface3DSeries. El puntero de selección va acompañado de una etiqueta que, por defecto, muestra el valor del punto de datos y las coordenadas del punto.
El rango de valores y el formato de la etiqueta que se muestra en el eje se pueden controlar con QValue3DAxis.
Para rotar el gráfico, mantenga presionado el botón derecho del mouse y muévalo. El zoom se realiza con la rueda del ratón. Ambos asumen que el controlador de entrada predeterminado está en uso.
Si no se establecen ejes explícitamente en Q3DSurface, se crean ejes predeterminados temporales sin etiquetas. Estos ejes predeterminados se pueden modificar a través del descriptor de acceso de ejes, pero tan pronto como se establezca explícitamente cualquier eje para una orientación, se destruirá el eje predeterminado para esa orientación.
Construya un gráfico plano Q3D mínimo
Primero, construya la superficie Q3D. Dado que en este ejemplo estamos ejecutando los gráficos como una ventana de nivel superior, debemos borrar el indicador Qt::FramelessWindowHint, que está configurado de manera predeterminada:
Q3DSurface surface;
surface.setFlags(surface.flags() ^ Qt::FramelessWindowHint);
Ahora el Q3DSurface está listo para recibir datos para renderizar. Crear elementos de datos para recibir valores:
QSurfaceDataArray *data = new QSurfaceDataArray;
QSurfaceDataRow *dataRow1 = new QSurfaceDataRow;
QSurfaceDataRow *dataRow2 = new QSurfaceDataRow;
Primero alimente los datos a los elementos de fila, luego agregue sus punteros a los elementos de datos:
*dataRow1 << QVector3D(0.0f, 0.1f, 0.5f) << QVector3D(1.0f, 0.5f, 0.5f);
*dataRow2 << QVector3D(0.0f, 1.8f, 1.0f) << QVector3D(1.0f, 1.2f, 1.0f);
*data << dataRow1 << dataRow2;、
Cree una nueva serie y establezca datos para ella:
QSurface3DSeries *series = new QSurface3DSeries;
series->dataProxy()->resetArray(data);
surface.addSeries(series);
Por último, hazlo visible:
surface.show();
El código completo requerido para crear y mostrar este gráfico es:
#include <QtDataVisualization>
using namespace QtDataVisualization;
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
Q3DSurface surface;
surface.setFlags(surface.flags() ^ Qt::FramelessWindowHint);
QSurfaceDataArray *data = new QSurfaceDataArray;
QSurfaceDataRow *dataRow1 = new QSurfaceDataRow;
QSurfaceDataRow *dataRow2 = new QSurfaceDataRow;
*dataRow1 << QVector3D(0.0f, 0.1f, 0.5f) << QVector3D(1.0f, 0.5f, 0.5f);
*dataRow2 << QVector3D(0.0f, 1.8f, 1.0f) << QVector3D(1.0f, 1.2f, 1.0f);
*data << dataRow1 << dataRow2;
QSurface3DSeries *series = new QSurface3DSeries;
series->dataProxy()->resetArray(data);
surface.addSeries(series);
surface.show();
return app.exec();
}
resultado de ejecución:
La escena se puede rotar, acercar y se puede seleccionar un elemento para ver su posición, pero otras interacciones no se incluyen en este ejemplo de código mínimo.
Análisis del proceso de construcción Q3Ddemo
Paso 1: Confirme la instalación del módulo QtDataVisualization
Cómo confirmarlo es verificar si hay una clase Q3dscatter en el archivo de ayuda. Generalmente, el archivo de ayuda correspondiente estará disponible solo después de instalar el módulo. De lo contrario, reinstale qt o instale el módulo por separado.
Paso 2: agregar módulos al archivo de configuración del proyecto
Q3d está en el módulo de visualización de datos y debe agregarse en el archivo de configuración pro o pri.
QT += datavisualization
Paso 3: agregue los archivos de encabezado utilizados
Úselo para agregar archivos de encabezado a las clases relacionadas con Q3DBar, use principalmente Q3DBar, QBar3DSeries, QBarDataRow, etc.
#include <Q3DBars>
#include <Q3DTheme>
#include <QBar3DSeries>
#include <QVector3D>
Paso 4: Agregar un espacio de nombres
En este momento, la clase correspondiente aún no se puede usar y se debe agregar el espacio de nombres:
using namespace QtDataVisualization;
Paso 5: marco de construcción base de iconos de Q3D
El siguiente es el proceso de construcción básico de Q3DSurface, incluidos los comentarios (tenga en cuenta la visualización del eje, consulte " Pit 1 " al final, preste atención a las reglas de superficie de los datos, consulte " Pit 2 "
_pQ3DSurface = new Q3DSurface();
_pContainer = QWidget::createWindowContainer(_pQ3DSurface, this);
// 设置轴文本
{
// 注意笛卡尔坐标
_pQ3DSurface->axisX()->setTitle("经度(°)");
_pQ3DSurface->axisX()->setTitleVisible(true);
_pQ3DSurface->axisY()->setTitle("高度(m)");
_pQ3DSurface->axisY()->setTitleVisible(true);
_pQ3DSurface->axisZ()->setTitle("纬度(°)");
_pQ3DSurface->axisZ()->setTitleVisible(true);
}
// 设置轴范围
{
// 注意笛卡尔坐标
_pQ3DSurface->axisX()->setRange(0, 359);
_pQ3DSurface->axisY()->setRange(0, 100);
_pQ3DSurface->axisZ()->setRange(0, 359);
}
// 生成一个曲线
_pSurface3DSeries = new QSurface3DSeries(_pQ3DSurface);
// 设置渲染平滑
_pSurface3DSeries->setMeshSmooth(true);
// 设置渲染模式
// DrawWireframe : 绘制栅格
// DrawSurface : 绘制表面
// DrawSurfaceAndWireframe : 绘制栅格和图表面
_pSurface3DSeries->setDrawMode(QSurface3DSeries::DrawSurface);
// 视图添加该曲线
_pQ3DSurface->addSeries(_pSurface3DSeries);
// 设置阴影质量
_pQ3DSurface->setShadowQuality(QAbstract3DGraph::ShadowQualitySoftLow);
// 设置视角
_pQ3DSurface->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetIsometricLeft);
// 设置子网格
_pQ3DSurface->activeTheme()->setGridEnabled(true);
#if 1
// 添加模拟数据
QSurfaceDataArray *pSurfaceDataArray = new QSurfaceDataArray;
#if 1
#if 1
// 这是 z 纬度
for(int n = 0; n < 360; n++)
{
QSurfaceDataRow *pSurfaceDataRow = new QSurfaceDataRow;
// 这是 x 经度
for(int m = 0; m < 360; m++)
{
// 注意与笛卡尔坐标进行映射
*pSurfaceDataRow << QVector3D(m, n / 7 + m / 7, n);
}
*pSurfaceDataArray << pSurfaceDataRow;
}
#else
for(int n = 0; n < 360; n++)
{
QSurfaceDataRow *pSurfaceDataRow = new QSurfaceDataRow;
// 这是 x 经度
for(int m = 0; m < 360; m++)
{
// 注意与笛卡尔坐标进行映射
*pSurfaceDataRow << QVector3D(m, qrand() % 100, n);
LOG << n << m;
}
*pSurfaceDataArray << pSurfaceDataRow;
}
#endif
#else
QSurfaceDataRow *pSurfaceDataRow1 = new QSurfaceDataRow;
QSurfaceDataRow *pSurfaceDataRow2 = new QSurfaceDataRow;
QSurfaceDataRow *pSurfaceDataRow3 = new QSurfaceDataRow;
// 行与行之间,要形成一个四点成面
*pSurfaceDataRow1 << QVector3D(0, 0, 0) << QVector3D(359, 20, 0);
*pSurfaceDataRow2 << QVector3D(50, 20, 179) << QVector3D(359, 40, 179);
*pSurfaceDataRow3 << QVector3D(100, 80, 359) << QVector3D(359, 100, 359);
*pSurfaceDataArray << pSurfaceDataRow1 << pSurfaceDataRow2 << pSurfaceDataRow3;
#endif
// 添加数据(自动冲掉之前的数据)
_pSurface3DSeries->dataProxy()->resetArray(pSurfaceDataArray);
#endif
_pQ3DSurface->addSeries(_pSurface3DSeries);
_pQ3DSurface->show();
código fuente de demostración
Q3dSurfaceWidget.h
#ifndef Q3DSURFACEWIDGET_H
#define Q3DSURFACEWIDGET_H
#include <QWidget>
#include <Q3DSurface>
#include <Q3DTheme>
#include <QSurface3DSeries>
#include <QVector3D>
using namespace QtDataVisualization;
namespace Ui {
class Q3dSurfaceWidget;
}
class Q3dSurfaceWidget : public QWidget
{
Q_OBJECT
public:
explicit Q3dSurfaceWidget(QWidget *parent = 0);
~Q3dSurfaceWidget();
protected:
void initControl();
protected:
void resizeEvent(QResizeEvent *event);
private:
Ui::Q3dSurfaceWidget *ui;
private:
Q3DSurface *_pQ3DSurface; // q3d平面曲线图
QWidget *_pContainer; // q3d窗口容器
QSurface3DSeries *_pSurface3DSeries ; // q3d柱状图数据
};
#endif // Q3DSURFACEWIDGET_H
Q3dSurfaceWidget.cpp
#include "Q3dSurfaceWidget.h"
#include "ui_Q3dSurfaceWidget.h"
#include <Q3DTheme>
#include <QDebug>
#include <QDateTime>
//#define LOG qDebug()<<__FILE__<<__LINE__
//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__
//#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread()
//#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd")
#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")
Q3dSurfaceWidget::Q3dSurfaceWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Q3dSurfaceWidget),
_pQ3DSurface(0),
_pContainer(0),
_pSurface3DSeries(0)
{
ui->setupUi(this);
QString version = "v1.0.0";
initControl();
}
Q3dSurfaceWidget::~Q3dSurfaceWidget()
{
delete ui;
}
void Q3dSurfaceWidget::initControl()
{
_pQ3DSurface = new Q3DSurface();
_pContainer = QWidget::createWindowContainer(_pQ3DSurface, this);
// 设置轴文本
{
// 注意笛卡尔坐标
_pQ3DSurface->axisX()->setTitle("经度(°)");
_pQ3DSurface->axisX()->setTitleVisible(true);
_pQ3DSurface->axisY()->setTitle("高度(m)");
_pQ3DSurface->axisY()->setTitleVisible(true);
_pQ3DSurface->axisZ()->setTitle("纬度(°)");
_pQ3DSurface->axisZ()->setTitleVisible(true);
}
// 设置轴范围
{
// 注意笛卡尔坐标
_pQ3DSurface->axisX()->setRange(0, 359);
_pQ3DSurface->axisY()->setRange(0, 100);
_pQ3DSurface->axisZ()->setRange(0, 359);
}
// 生成一个曲线
_pSurface3DSeries = new QSurface3DSeries(_pQ3DSurface);
// 设置渲染平滑
_pSurface3DSeries->setMeshSmooth(true);
// 设置渲染模式
// DrawWireframe : 绘制栅格
// DrawSurface : 绘制表面
// DrawSurfaceAndWireframe : 绘制栅格和图表面
_pSurface3DSeries->setDrawMode(QSurface3DSeries::DrawSurface);
// 视图添加该曲线
_pQ3DSurface->addSeries(_pSurface3DSeries);
// 设置阴影质量
_pQ3DSurface->setShadowQuality(QAbstract3DGraph::ShadowQualitySoftLow);
// 设置视角
_pQ3DSurface->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetIsometricLeft);
// 设置子网格
_pQ3DSurface->activeTheme()->setGridEnabled(true);
#if 1
// 添加模拟数据
QSurfaceDataArray *pSurfaceDataArray = new QSurfaceDataArray;
#if 1
#if 1
// 这是 z 纬度
for(int n = 0; n < 360; n++)
{
QSurfaceDataRow *pSurfaceDataRow = new QSurfaceDataRow;
// 这是 x 经度
for(int m = 0; m < 360; m++)
{
// 注意与笛卡尔坐标进行映射
*pSurfaceDataRow << QVector3D(m, n / 7 + m / 7, n);
}
*pSurfaceDataArray << pSurfaceDataRow;
}
#else
for(int n = 0; n < 360; n++)
{
QSurfaceDataRow *pSurfaceDataRow = new QSurfaceDataRow;
// 这是 x 经度
for(int m = 0; m < 360; m++)
{
// 注意与笛卡尔坐标进行映射
*pSurfaceDataRow << QVector3D(m, qrand() % 100, n);
LOG << n << m;
}
*pSurfaceDataArray << pSurfaceDataRow;
}
#endif
#else
QSurfaceDataRow *pSurfaceDataRow1 = new QSurfaceDataRow;
QSurfaceDataRow *pSurfaceDataRow2 = new QSurfaceDataRow;
QSurfaceDataRow *pSurfaceDataRow3 = new QSurfaceDataRow;
// 行与行之间,要形成一个四点成面
*pSurfaceDataRow1 << QVector3D(0, 0, 0) << QVector3D(359, 20, 0);
*pSurfaceDataRow2 << QVector3D(50, 20, 179) << QVector3D(359, 40, 179);
*pSurfaceDataRow3 << QVector3D(100, 80, 359) << QVector3D(359, 100, 359);
*pSurfaceDataArray << pSurfaceDataRow1 << pSurfaceDataRow2 << pSurfaceDataRow3;
#endif
// 添加数据(自动冲掉之前的数据)
_pSurface3DSeries->dataProxy()->resetArray(pSurfaceDataArray);
#endif
_pQ3DSurface->addSeries(_pSurface3DSeries);
_pQ3DSurface->show();
}
void Q3dSurfaceWidget::resizeEvent(QResizeEvent *event)
{
if(_pContainer)
{
_pContainer->setGeometry(rect());
}
}
Plantilla de proyecto v1.2.0
en el hoyo
Hoyo 1: El sistema de coordenadas xyz es incorrecto
pregunta
error de mapeo de precisión x, dimensión y, altura z (altitud)
razón
x, y, z en realidad siguen el conjunto de coordenadas cartesianas
resolver
Primero comprenda las coordenadas, y luego la dirección del eje z, los datos también deben reemplazarse (organizados de acuerdo con x, y, z, cambiados a x, z, y)
&emso;
Entrada 2: la superficie curva se muestra incorrectamente
pregunta
Error de asignación de visualización de datos
razón
Los puntos en una superficie deben seguir la regla de 4 puntos en una superficie, que es similar al principio de opengl relacionado con 3 puntos en una superficie y 4 puntos en una superficie.
resolver
Entre filas y filas adyacentes, se debe formar una superficie.Después de la modificación, se mostrará de la siguiente manera:
Anterior: " Tecnología de desarrollo de Qt: Notas de desarrollo de gráficos Q3D (2): Introducción al histograma 3D de Q3DBar, demostración y explicación detallada del código "
Siguiente: Estén atentos...
Si el artículo es un artículo original, indique la fuente del artículo original al reproducirlo.
La dirección del blog de este artículo: https://hpzwl.blog.csdn.net/article/details/130264470