You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

580 lines
14 KiB
C++

1 month ago
#include "viewwidget.h"
#include <QPainter>
#include <thread>
#include <functional>
using namespace std;
//#include "coutlinedetector.h"
ViewWidget::ViewWidget(QWidget *parent) : MyColorMap(parent)
, m_type(colorfulmap)
,m_bTransparentColormap(false)
{
// this->setStyleSheet("QWidget { border: 1px solid black; }");
// 设置边框样式
//this->setBackgroundRole(QPalette::Light);
//this->setFrameShape(QFrame::Box);
}
//重置坐标框范围
void ViewWidget::resetAxisRect(void)
{
m_dispCoordsRect.setCoords(0,0,0,0);
}
//保存当前坐标框范围到m_axisRect
void ViewWidget::saveCurrentAxisRect(void)
{
m_dispCoordsRect.setLeft(this->xAxis->range().lower);
m_dispCoordsRect.setRight(this->xAxis->range().upper);
m_dispCoordsRect.setBottom(this->yAxis->range().lower);
m_dispCoordsRect.setTop(this->yAxis->range().upper);
;
}
void ViewWidget::updateDraw()
{
//重绘
disconnect(m_colorScale, &QCPColorScale::dataRangeChanged,this, &ViewWidget::slotScaleRangeChanged);
clearPlottables();
clearGraphs();
if(nullptr == m_pGrid)
{
replot(QCustomPlot::rpQueuedReplot);
return;
}
QCustomPlot* customPlot = this;
QString demoName = " Amplitude Color Map";
// configure axis rect:
customPlot->setInteractions(QCP::iRangeDrag|QCP::iRangeZoom); // this will also allow rescaling the color scale by dragging/zooming
customPlot->axisRect()->setupFullAxesBox(true);
customPlot->xAxis->setLabel(m_strXLabel);
customPlot->yAxis->setLabel(m_strYLabel);
// set up the QCPColorMap:
QCPColorMap *colorMap = new QCPColorMap(customPlot->xAxis, customPlot->yAxis);
int nx = m_pGrid->XNum()-1;
int ny = m_pGrid->YNum()-1;
double xmin = m_pGrid->X(0);
double ymin = m_pGrid->Y(0);
double xmax = m_pGrid->X(nx);
double ymax = m_pGrid->Y(ny);
double* zrange = m_pGrid->GetRange();
double zmin = zrange[0];
double zmax = zrange[1];
zmin -= 1e-4;
zmax += 1e-4;
colorMap->data()->setSize(nx, ny); // we want the color map to have nx * ny data points
colorMap->data()->setRange(QCPRange(xmin,xmax), QCPRange(ymin,ymax)); // and span the coordinate range -4..4 in both key (x) and value (y) dimensions
// now we assign some data, by accessing the QCPColorMapData instance of the color map:
double x, y, z;
// float zmin = 1e31, zmax = -10;
for (int xIndex=0; xIndex<nx; ++xIndex)
{
for (int yIndex=0; yIndex<ny; ++yIndex)
{
colorMap->data()->cellToCoord(xIndex, yIndex, &x, &y);
z = m_pGrid->Z(xIndex,yIndex);
//越界数据赋空值
if(z < zmin || z > zmax || m_bTransparentColormap)
{
z = 1e20;
}
colorMap->data()->setCell(xIndex, yIndex,z);
// zmin = std::fmin(zmin,(z1+z2)/2.0);
// zmax = std::fmax(zmax,(z1+z2)/2.0);
}
}
zmin += 1e-4;
zmax -= 1e-4;
// qDebug() << "zmin = " << zmin << " zmax = " << zmax;
// add a color scale:
QCPColorScale *colorScale = m_colorScale;
if(nullptr == m_colorScale)
{
m_colorScale = new QCPColorScale(customPlot);
colorScale = m_colorScale; // new QCPColorScale(customPlot);
customPlot->plotLayout()->addElement(0, 1, colorScale); // add it to the right of the main axis rect
colorScale->setType(QCPAxis::atRight); // scale shall be vertical bar with tick/axis labels right (actually atRight is already the default)
}
colorMap->setColorScale(colorScale); // associate the color map with the color scale
// colorScale->setLabel("幅值");
// colorScale->axis()->setLabel("幅度差");
// set the color gradient of the color map to one of the presets:
switch(m_type)
{
case colorfulmap:
case colorfulmap_contours:
default:
{
QCPColorGradient gradient(QCPColorGradient::gpSpectrum); //定义一个渐变对象
// if(m_bTransparentColormap)
// {
// gradient.setColorStopAt(0, Qt::transparent); //设置特殊数值的颜色为透明色
// gradient.setColorStopAt(1, Qt::transparent);
// }
colorMap->setGradient(gradient); //将设置好的渐变对象赋给colormap
//colorMap->setGradient(QCPColorGradient::gpSpectrum);
}
break;
case graymap:
colorMap->setGradient(QCPColorGradient::gpGrayscale);
break;
}
// we could have also created a QCPColorGradient instance and added own colors to
// the gradient, see the documentation of QCPColorGradient for what's possible.
// rescale the data dimension (color) such that all data points lie in the span visualized by the color gradient:
colorMap->rescaleDataRange();
QCPRange range(zmin, zmax);
colorMap->setDataRange(range);
if(graymap != m_type && m_colorScaleRange.size() > 1)
{
colorMap->colorScale()->setDataRange(m_colorScaleRange);
}
//colorMap->setDataRange(QCPRange(3,5));
// if(colorful == m_type)
// {
// //begin test
// colorMap->setDataRange(QCPRange(zmin,zmax));
// QCPColorGradient gradient = colorMap->gradient();
// gradient.setColorStopAt(zmax+1,Qt::white);
// gradient.setColorStopAt(zmax+10,Qt::white);
// // gradient.setColorStopAt(-1,Qt::white);
// colorMap->setGradient(gradient);
// // colorMap->rescaleDataRange();
// //end test
// }
// 禁用科学计数法
xAxis->setNumberFormat("g");
yAxis->setNumberFormat("g");
// 设置精度
xAxis->setNumberPrecision(8);
yAxis->setNumberPrecision(8);
// make sure the axis rect and color scale synchronize their bottom and top margins (so they line up):
QCPMarginGroup *marginGroup = new QCPMarginGroup(customPlot);
customPlot->axisRect()->setMarginGroup(QCP::msBottom|QCP::msTop, marginGroup);
colorScale->setMarginGroup(QCP::msBottom|QCP::msTop, marginGroup);
//如果绘制轮廓线
if( colorfulmap_contours == m_type && m_contours.size() > 0)
{
QTime t1; t1.start();
drawContours();
qDebug()<< "drawcontours time elapsed: "<< t1.elapsed() << " ms";
}
// rescale the key (x) and value (y) axes so the whole color map is visible:
customPlot->rescaleAxes();
refreshAxis();
//replot(QCustomPlot::rpQueuedReplot);
connect(m_colorScale, &QCPColorScale::dataRangeChanged,this, &ViewWidget::slotScaleRangeChanged);
// // 固定纵横比
// setFixedSize(800, 600); // 设置绘图区域的固定大小
}
//void ViewWidget::setImage(const QImage& img, bool bUpdate)
//{
// m_img = img;
// if(bUpdate)
// this->update();
//}
//void ViewWidget::showEvent(QShowEvent *event)
//{
// this->setStyleSheet("QWidget { border: 1px solid black; }");
//}
//void ViewWidget::paintEvent(QPaintEvent *event)
//{
////painter.fillRect(rt,Qt::white);
// if(m_img.isNull())
// return;
//// img = QImage(rt.width(),rt.height(),QImage::Format_ARGB32);
//// img.fill(Qt::white);
// QRect rt = this->contentsRect();
// rt.adjust(1,1,-1,-1);
// QPainter painter(this);
// QImage img = m_img.scaled(rt.width(),rt.height(),Qt::KeepAspectRatio);
// painter.drawImage(rt.left() +(rt.width()-img.width())/2,rt.top()+(rt.height()-img.height())/2,img);
//}
//void ViewWidget::resizeEvent(QResizeEvent *event)
//{
// this->update();
//}
//void ViewWidget::mouseDoubleClickEvent(QMouseEvent *event)
//{
// if(m_img.isNull())
// return;
// cv::Mat mat;
// COutlineDetector::ConvertQImageToMat(m_img,mat);
// cv::namedWindow("image",WINDOW_NORMAL);
// cv::imshow("image",mat);
// cv::waitKey(0);
//}
//设置轮廓线
void ViewWidget::setContours(vector< vector<cv::Point2f> >& contours)
{
m_contours.assign(contours.begin(),contours.end() );
}
//清空轮廓线
void ViewWidget::clearContours(void)
{
m_contours.clear();
}
void ViewWidget::drawContours()
{
// 添加黑色曲线
clearItems();
// QVector<double> xs;
// QVector<double> ys;
// QPen pen(Qt::black);
// int j = 0;
// for(auto& p: m_contours)
// {
// int igraph = this->graphCount();
// this->addGraph();
// xs.clear(); ys.clear();
// xs.resize(p.size()+1);
// ys.resize(p.size()+1);
// int i = 0;
// for(i = 0; i < p.size(); i ++ )
// {
// xs[i] = p[i].x;
// ys[i] = p[i].y;
// }
// xs[i] = p[0].x;
// ys[i] = p[0].y;
// graph(igraph)->addData(xs,ys,true);
// graph(igraph)->setPen(pen);
// }
for(auto& p: m_contours)
{
QCPItemLine* line = nullptr;
int i = 0;
for( i = 0; i < p.size()-1; i ++ )
{
line = new QCPItemLine(this);
line->start->setCoords(p[i].x,p[i].y);
line->end->setCoords(p[i+1].x,p[i+1].y);
line->setPen(QPen(Qt::black));
}
line = new QCPItemLine(this);
line->start->setCoords(p[i].x,p[i].y);
line->end->setCoords(p[0].x,p[0].y);
line->setPen(QPen(Qt::black));
// // 添加多边形到图层上
// QCPItemCurve *polygon1 = new QCPItemCurve(this);
// // 设置第一个多边形的顶点
// QVector<QPointF> polygon1Points;
// polygon1Points.resize(p.size()+1);
// int i = 0;
// for( i = 0; i < p.size(); i ++ )
// {
// polygon1Points[i] = QPointF(p[i].x,p[i].y);
// }
// polygon1Points[i] = QPointF(p[0].x,p[0].y);
// polygon1->setPen(QPen(Qt::black)); // 设置多边形的线条样式
// polygon1->setHead(QCPLineEnding::esNone); // 不显示线条末端箭头
// polygon1->setTail(QCPLineEnding::esNone); // 不显示线条末端箭头
// polygon1
}
// // 添加多边形到图层上
// QCPItemCurve *polygon1 = new QCPItemCurve(this);
// // 设置第一个多边形的顶点
// QVector<QPointF> polygon1Points;
// polygon1Points << QPointF(0, 0) << QPointF(100, 0) << QPointF(100, 100) << QPointF(0, 100) << QPointF(0, 0);
// polygon1->setPen(QPen(Qt::black)); // 设置多边形的线条样式
// polygon1->setHead(QCPLineEnding::esNone); // 不显示线条末端箭头
// polygon1->setTail(QCPLineEnding::esNone); // 不显示线条末端箭头
// polygon1->setCurveData(polygon1Points);
// // 设置第二个多边形的顶点
// QVector<QPointF> polygon2Points;
// polygon2Points << QPointF(50, 50) << QPointF(150, 50) << QPointF(150, 150) << QPointF(50, 150) << QPointF(50, 50);
// polygon2->setPen(QPen(Qt::black)); // 设置多边形的线条样式
// polygon2->setHead(QCPLineEnding::esNone); // 不显示线条末端箭头
// polygon2->setTail(QCPLineEnding::esNone); // 不显示线条末端箭头
// polygon2->setCurveData(polygon2Points);
// // 将多边形添加到图表中
// customPlot.addItem(polygon1);
// customPlot.addItem(polygon2);
}
void ViewWidget::slotScaleRangeChanged(const QCPRange& newRange)
{
if(graymap != m_type)
m_colorScaleRange = newRange;
}
void ViewWidget::refreshAxis(void)
{
QCustomPlot* customPlot = this;
QRectF axisRect = customPlot->axisRect()->rect(); // 获取绘图区域的矩形
QCPColorScale* colorScale = m_colorScale;
// qDebug() << colorScale->margins().left() << " " << colorScale->margins().right();
double colorMapWidth = axisRect.width();// - colorScale->axis()->offset() - colorScale->barWidth() ; // 计算 colormap 区域的宽度
double colorMapHeight = axisRect.height(); // colormap 区域的高度
// qDebug() << "width = " << colorMapWidth;
// qDebug() << "height= " << colorMapHeight;
//实际坐标宽和高
// double xsz = customPlot->xAxis->range().size();
// double ysz = customPlot->yAxis->range().size();
int nx = m_pGrid->XNum()-1;
int ny = m_pGrid->YNum()-1;
//显示的坐标范围
double xmin = m_pGrid->X(0);
double ymin = m_pGrid->Y(0);
double xmax = m_pGrid->X(nx);
double ymax = m_pGrid->Y(ny);
if(m_dispCoordsRect.width() > 1 && m_dispCoordsRect.height() < -1)
{
xmin = m_dispCoordsRect.left();
if(xmin < m_pGrid->X(0))
xmin = m_pGrid->X(0);
ymin = m_dispCoordsRect.bottom();
if(ymin < m_pGrid->Y(0))
ymin = m_pGrid->Y(0);
xmax = min(m_dispCoordsRect.right(),m_pGrid->X(nx));
ymax = min(m_dispCoordsRect.top(),m_pGrid->Y(ny));
}
double xsz = xmax -xmin;
double ysz = ymax-ymin;
double pixelFactor = colorMapHeight/colorMapWidth; //像素宽高纵横比
double coordFactor = ysz/xsz; //实际坐标纵横比
// qDebug() << "窗口宽高 w h: " << colorMapWidth << " " << colorMapHeight << " " << 1.0/pixelFactor;
// qDebug() << "实际坐标纵横比 " << 1./coordFactor;
double span = 0;
// if(fabs(coordFactor/pixelFactor-1.0) < 1e-3)
// {
// replot(QCustomPlot::rpQueuedReplot); //重绘
// return;
// }
if(coordFactor > pixelFactor) //实际坐标过高,补宽度
{
//ysz/pixelFactor 等比情况下x的范围
span = ysz/pixelFactor - xsz;
xmax += span;
}
else
{
span = xsz * pixelFactor -ysz;
ymax += span;
}
// qDebug() << "span = " << span << "xmax = " <<xmax << " ymax = " << ymax;
customPlot->xAxis->setRange(xmin,xmax);
customPlot->yAxis->setRange(ymin,ymax);
replot(QCustomPlot::rpQueuedReplot); //重绘
}
void ViewWidget::resizeEvent(QResizeEvent *event)
{
saveCurrentAxisRect();
MyColorMap::resizeEvent(event);
if(nullptr != m_pGrid)
{
refreshAxis();
// updateDraw();
}
}
//void ViewWidget::changeEvent(QEvent *event)
//{
// if (event->type() == QEvent::WindowStateChange)
// {
// if (windowState() & Qt::WindowMaximized)
// {
// if(nullptr != m_pGrid)
// {
// refreshAxis();
// // updateDraw();
// }
// }
// }
//}