gpt4 book ai didi

Qt开发技术:Q3D图表开发笔记(三):Q3DSurface三维曲面图介绍、Demo以及代码详解

转载 作者:我是一只小鸟 更新时间:2023-04-20 14:31:12 26 4
gpt4 key购买 nike

前言

  qt提供了q3d进行三维开发,虽然这个框架没有得到大量运用也不是那么成功,性能上也有很大的欠缺,但是普通的点到为止的应用展示还是可以的。   其中就包括华丽绚烂的三维图表,数据量不大的时候是可以使用的。   前面介绍了基础的q3d散点图、柱状图,本篇介绍基础的三维曲面图.

 

Demo:Q3DSurface散点图演示效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

 

Q3D提供的三维图表

  依赖QtDataVisualization。在安装qt的时候要选择安装QtDataVisualization模块.

Q3DScatter散点图

  Q3D的散点图,性能大约支撑1000个点可以不卡顿,具体依赖pc,1000个点是什么 概念,可以理解为:10x10x10的区域,每个区域一个数据点.

Q3DBars柱状图

  Q3D的柱状图,性能跟散点图类似。     。

Q3DSurface平面凹凸图,平面纹理图,平面曲线图

  Q3D的柱状图,性能跟散点图类似.

 

Q3DSurface平面曲线图

简介

  Q3DSurface类提供了渲染3D曲面图的方法。该类使开发人员能够渲染3D表面图,并通过自由旋转场景来查看它们。可以通过QSurface3DSeries控制曲面的视觉财产,例如绘制模式和着色。   Q3DSurface通过在用户用鼠标左键点击的数据点上显示高亮显示的球(当使用默认输入处理程序时)或通过QSurface3DSeries进行选择来支持选择。选择指针附带一个标签,在默认情况下,该标签显示数据点的值和点的坐标。 轴上显示的值范围和标签格式可以通过QValue3DAxis进行控制。   要旋转图形,请按住鼠标右键并移动鼠标。缩放是使用鼠标滚轮完成的。两者都假设默认的输入处理程序正在使用中。   如果没有将任何轴明确设置为Q3DSurface,则会创建不带标签的临时默认轴。这些默认轴可以通过轴访问器进行修改,但只要明确设置了方向的任何轴,该方向的默认轴就会被破坏.

构造最小Q3D平面曲线图

  首先,构造Q3D曲面。由于在本例中,我们将图形作为顶级窗口运行,因此需要清除Qt::FramelessWindowHint标志,该标志在默认情况下设置:

                          
                            Q3DSurface surface
                             ; surface  .  setFlags  (surface  .  flags  (  )  ^ Qt  ::FramelessWindowHint  )  ;            
                          
                        

  现在Q3DSurface已准备好接收要渲染的数据。创建数据元素以接收值:

                          
                            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  (  )  ;     
                          
                        

  创建和显示此图所需的完整代码为:

                          
                              #  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  (  )  ;  }                                                                                                                        
                          
                        

  运行效果:

  场景可以被旋转、放大,并且可以选择一个项目来查看其位置,但在这个最小的代码示例中不包括其他交互.

 

Q3Ddemo构建流程解析

步骤一:确认安装QtDataVisualization模块

  如何确认,则是在帮助文件中查看是否有Q3dscatter类。一般是安装了模块才会有对应的帮助文件。没有则重新安装qt或者单独安装该模块.

步骤二:工程配置文件中加入模块

  Q3d是在数据可视化模块中,需要在pro或者pri配置文件中添加.

                          
                            QT 
                             += datavisualization 
                          
                        

在这里插入图片描述

步骤三:添加使用到的头文件

  使用到Q3DBar相关类中添加头文件,主要使用到Q3DBar、QBar3DSeries、QBarDataRow等等.

                          
                              #  include  <Q3DBars>   #  include  <Q3DTheme>   #  include  <QBar3DSeries>   #  include  <QVector3D>                
                          
                        

在这里插入图片描述

步骤四:添加命名空间

  这时候还是无法使用对应的类,需要添加命名空间才行:

                          
                             using  namespace QtDataVisualization  ;   
                          
                        

在这里插入图片描述

步骤五:Q3D的图标基础构建框架

  下面是包含注释的Q3DSurface基础构建流程(注意轴的显示,查看末尾“入坑一”,注意数据的成面规则,查看“入坑二” 。

                          
                            _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  (  )  ;                                                                                                                                                                                                                                                                                                                                                                                                                               
                          
                        
 

Demo源码

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   (   )   )   ;   }   }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
                          
                        
 

工程模板v1.2.0

在这里插入图片描述

 

入坑

入坑一:xyz坐标系不对

问题

  x精度,y维度,z高度(海拔高度)映射错误 。

原因

  x,y,z实际是遵循笛卡尔坐标集 。

解决

  先理解坐标,然后z轴方向,数据也要替换(按照x,y,z来排列,改为x,z,y)  &emso,

入坑二:曲面显示不对

问题

  数据显示映射错误 。

原因

  点成面,需要遵循4点成面的规则,和opengl相关3点成面和4点成面的原理类似.

在这里插入图片描述

解决

  相邻行与行之间,要形成面,修改后展示如下:

在这里插入图片描述
在这里插入图片描述

最后此篇关于Qt开发技术:Q3D图表开发笔记(三):Q3DSurface三维曲面图介绍、Demo以及代码详解的文章就讲到这里了,如果你想了解更多关于Qt开发技术:Q3D图表开发笔记(三):Q3DSurface三维曲面图介绍、Demo以及代码详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com