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++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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