基于qwtplot3d的QT 3d 波形显示
qwtplot3d下载地址:
https://github.com/sintegrial/qwtplot3d
示例运行效果
部分代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 QtWidgets3DTest::QtWidgets3DTest(QWidget *parent) 2 : QMainWindow(parent) 3 { 4 ui.setupUi(this); 5 6 QGridLayout *grid = new QGridLayout(ui.frame); 7 dataWidget = new GridPlot(ui.frame); 8 grid->addWidget(dataWidget, 0, 0); 9 10 //ui.btnColor->setVisible(false); 11 ui.cbxDataType->addItem("Default"); 12 ui.cbxDataType->addItem("Sine"); 13 ui.cbxDataType->addItem("White Noise"); 14 15 ui.cbxAxisStyle->addItem("Box"); 16 ui.cbxAxisStyle->addItem("XYZ"); 17 ui.cbxAxisStyle->addItem("None"); 18 19 ui.cbxStyle->addItem("point"); 20 ui.cbxStyle->addItem("wireframe"); 21 ui.cbxStyle->addItem("hiddenline"); 22 ui.cbxStyle->addItem("polygon"); 23 ui.cbxStyle->addItem("filledmesh"); 24 ui.cbxStyle->addItem("NoData"); 25 26 connect(ui.btnReset, SIGNAL(clicked()), this, SLOT(setStandardView())); 27 connect(ui.btnRotate, SIGNAL(clicked()), this, SLOT(pickAnimation())); 28 29 connect(ui.cbxDataType, SIGNAL(currentIndexChanged(int)), this, SLOT(pickDataStyle(int))); 30 connect(ui.cbxAxisStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(pickCoordSystem(int))); 31 connect(ui.cbxStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(pickPlotStyle(int))); 32 33 connect(ui.chxMouse, SIGNAL(toggled(bool)), dataWidget, SLOT(enableMouse(bool))); 34 connect(ui.chxProjection, SIGNAL(toggled(bool)), this, SLOT(toggleProjectionMode(bool))); 35 connect(ui.chxColorlegend, SIGNAL(toggled(bool)), this, SLOT(toggleColorLegend(bool))); 36 connect(ui.chxAutoscale, SIGNAL(toggled(bool)), this, SLOT(toggleAutoScale(bool))); 37 connect(ui.chxShader, SIGNAL(toggled(bool)), this, SLOT(toggleShader(bool))); 38 39 connect(&timerWaterfall, SIGNAL(timeout()), this, SLOT(UpdateData())); 40 rotateTimer = new QTimer(this); 41 connect(rotateTimer, SIGNAL(timeout()), this, SLOT(rotate())); 42 43 dataWidget->coordinates()->setLineSmooth(true); 44 dataWidget->setRenderThreadsCount(8); 45 setStandardView(); 46 resetColors(); 47 resetFonts(); 48 dataWidget->enableMouse(true); 49 dataWidget->setKeySpeed(15, 20, 20); 50 51 dataWidget->setPlotStyle(FILLED);//polygon 52 ui.cbxStyle->setCurrentIndex(3); 53 toggleAutoScale(false); 54 toggleShader(false); 55 //timerWaterfall.stop(); 56 ui.cbxDataType->setCurrentIndex(1);//Sine 57 ui.cbxAxisStyle->setCurrentIndex(1);//XYZ 58 pickDataStyle(1); 59 } 60 61 void QtWidgets3DTest::pickDataStyle(int idx) 62 { 63 if (idx == 1) 64 { 65 InitSineWaterfallData(); 66 } 67 else if (idx == 2) 68 { 69 70 } 71 else 72 { 73 InitWaterfallData(); 74 } 75 dataWidget->update(); 76 } 77 78 void QtWidgets3DTest::InitWaterfallData() 79 { 80 // fill initial data 81 for (int i = 0; i < colmums; i++) 82 { 83 dataWaterfall[i] = new double[rows]; 84 double zval = 50; 85 for (int j = 0; j < rows; j++) 86 { 87 dataWaterfall[i][j] = zval; 88 zval = zval+ rand() % 3 - 1; 89 } 90 } 91 timerWaterfall.setInterval(50); 92 timerWaterfall.start(); 93 } 94 95 void QtWidgets3DTest::UpdateData() 96 { 97 if (ui.cbxDataType->currentIndex() == 1) 98 { 99 double armp = qrand() % (5, 100); 100 for (int i = 0; i < colmums; i++) 101 { 102 for (int j = 1; j < rows; j++) 103 { 104 /*if ( j % 5 == 0) 105 dataWaterfall[i][j - 1] = std::numeric_limits<double>::quiet_NaN(); 106 else*/ 107 dataWaterfall[i][j - 1] = dataWaterfall[i][j]; 108 } 109 } 110 for (int i = 0; i < colmums; i++) 111 { 112 double t = (float)i / rows; 113 double zval = 0; 114 //if (i % 3 == 0|| i % 5 == 0) 115 // zval = std::numeric_limits<double>::quiet_NaN();//减少数据密度,增加运行速度 by yanglk 15923358280 116 //else 117 zval = armp * sin(2 * PI * frequencySine * t); 118 119 dataWaterfall[i][rows - 1] = zval; 120 } 121 } 122 else 123 { 124 for (int i = 0; i < colmums; i++) 125 { 126 for (int j = 1; j < rows; j++) 127 { 128 dataWaterfall[i][j - 1] = dataWaterfall[i][j]; 129 } 130 } 131 double zval = 50; 132 for (int i = 0; i < colmums; i++) 133 { 134 dataWaterfall[i][rows - 1] = zval; 135 zval += rand() % 3 - 1; 136 if (rand() % 5 == 1) 137 dataWaterfall[i][rows - 1] = std::numeric_limits<double>::quiet_NaN(); 138 } 139 } 140 141 QElapsedTimer tim; 142 tim.start(); 143 int ylen = rows * 6; 144 // update dataset 145 dataWidget->createDataset(dataWaterfall, colmums, rows, 0, colmums, 0, ylen); 146 147 qint64 rate = tim.elapsed(); 148 dataWidget->setTitle(QString("Dynamic Plotter Demon - Frame Time %1 ms").arg(rate)); 149 dataWidget->coordinates()->axes[X1].setLabelString("Size"); 150 dataWidget->coordinates()->axes[Y1].setLabelString("Times"); 151 dataWidget->coordinates()->axes[Z1].setLabelString("Amplitude"); 152 //dataWidget->setResolution(0); 153 dataWidget->update(); 154 } 155 156 void QtWidgets3DTest::InitSineWaterfallData() 157 { 158 // fill initial data 159 for (int i = 0; i < colmums; i++) 160 { 161 dataWaterfall[i] = new double[rows]; 162 for (int j = 0; j < rows; j++) 163 { 164 dataWaterfall[i][j] = std::numeric_limits<double>::quiet_NaN(); 165 } 166 } 167 for (int i = 0; i < colmums; i++) 168 { 169 double t = (float)i / colmums; 170 double zval = amplitudeSine * sin(2 * PI * frequencySine * t); 171 dataWaterfall[i][0] = zval; 172 } 173 timerWaterfall.setInterval(50); 174 timerWaterfall.start(); 175 }
说明
1,dataWidget->createDataset(dataWaterfall, colmums, rows, 0, colmums, 0, ylen);“colmums, rows”可设置X轴Y轴的间隔和刻度
2,\src\qwt3d_gridplot.cpp,GridPlot::CVertexProcessor::run()方法是画格子线的,如果只想画一个方向的线条,可以注释点另一个方向的画线逻辑
3,如果不需要法线,可以注释掉带“Normals”的相关方法。
待实现:
1,鼠标获取当前XYZ值,以及当前XYZ轴的上所有点的颜色
2,增加X轴Y轴光标。
如需要原码可联系