730 lines
25 KiB
C++
730 lines
25 KiB
C++
![]() |
#include "plotwidget.h"
|
|||
|
#include "xlsxdocument.h"
|
|||
|
extern QStringList slist_temper;
|
|||
|
extern QStringList slist_dsc;
|
|||
|
extern QString g_sname_string;
|
|||
|
extern double g_quality;
|
|||
|
double g_area;
|
|||
|
double g_kmin;
|
|||
|
double g_b_tang1;
|
|||
|
double g_target_x1;
|
|||
|
double g_target_y1;
|
|||
|
double g_kmax;
|
|||
|
double g_b_tang2;
|
|||
|
double g_target_x2;
|
|||
|
double g_target_y2;
|
|||
|
|
|||
|
|
|||
|
PlotWidget::PlotWidget(QWidget *parent) : QWidget(parent)
|
|||
|
{
|
|||
|
qRegisterMetaType<QVariant>("QVariant");
|
|||
|
|
|||
|
m_xlsx = new QXlsx::Document(this);
|
|||
|
|
|||
|
m_customPlot = new QCustomPlot(this);
|
|||
|
QVBoxLayout *layout = new QVBoxLayout(this);
|
|||
|
layout->addWidget(m_customPlot);
|
|||
|
|
|||
|
m_label_left = new QLabel(this);
|
|||
|
m_label_left->setGeometry(80, 70, 60, 20);
|
|||
|
m_label_left->setText(QObject::tr("左选线:"));
|
|||
|
m_lineEdit_left = new QLineEdit(this);
|
|||
|
m_lineEdit_left->setGeometry(130, 70, 60, 20);
|
|||
|
|
|||
|
m_label_right = new QLabel(this);
|
|||
|
m_label_right->setText(QObject::tr("右选线:"));
|
|||
|
m_label_right->setGeometry(80, 100, 60, 20);
|
|||
|
m_lineEdit_right = new QLineEdit(this);
|
|||
|
m_lineEdit_right->setGeometry(130, 100, 60, 20);
|
|||
|
|
|||
|
m_clear_button = new QPushButton(this);
|
|||
|
m_clear_button->setText(QObject::tr("清除曲线"));
|
|||
|
m_clear_button->setGeometry(80, 130, 110, 20);
|
|||
|
|
|||
|
// m_save_button = new QPushButton(this);
|
|||
|
// m_save_button->setText(QObject::tr("保存数据"));
|
|||
|
// m_save_button->setGeometry(80, 152, 110, 20);
|
|||
|
|
|||
|
///m_itemLine = new QCPItemLine(m_customPlot);
|
|||
|
|
|||
|
m_count_graph = 0;
|
|||
|
setupPlot();
|
|||
|
plotWaterfall();
|
|||
|
|
|||
|
//建立槽函数
|
|||
|
connect(m_customPlot, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(mousePress(QMouseEvent*)));
|
|||
|
connect(m_customPlot, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMove(QMouseEvent*)));
|
|||
|
connect(m_customPlot, SIGNAL(mouseRelease(QMouseEvent*)), this, SLOT(mouseRelease()));
|
|||
|
connect(m_customPlot, SIGNAL(selectionChangedByUser()), this, SLOT(selectionChanged()));
|
|||
|
|
|||
|
connect(this, SIGNAL(send_line_data_to_plot(QVariant, QVariant)), this, SLOT(plot_connect_line(QVariant, QVariant)));
|
|||
|
connect(this, SIGNAL(show_min_point(double, double)), this, SLOT(show_min_point_text(double, double)));
|
|||
|
// connect(m_customPlot,&QCustomPlot::mouseDoubleClick,this,[=]{ //双击效果不理想
|
|||
|
// m_customPlot->rescaleAxes();
|
|||
|
// // m_customPlot->xAxis->rescale();
|
|||
|
// // m_customPlot->yAxis->rescale();
|
|||
|
// m_customPlot->replot();
|
|||
|
// });
|
|||
|
|
|||
|
connect(m_clear_button, SIGNAL(clicked()), this, SLOT(clear_all_graph()));
|
|||
|
///connect(m_save_button, SIGNAL(clicked()), this, SLOT(save_sample_quality_area_data()));
|
|||
|
|
|||
|
m_customPlot->xAxis->setRange(0, 1000, Qt::AlignCenter);
|
|||
|
m_customPlot->yAxis->setRange(0, 1000, Qt::AlignCenter);
|
|||
|
|
|||
|
///m_customPlot->legend->setVisible(true);
|
|||
|
///m_customPlot->legend->setSelectableParts(QCPLegend::spItems);//图例本身不能被选择,只有里面的项可以被选择
|
|||
|
///m_customPlot->legend->setSelectedIconBorderPen(Qt::NoPen);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
PlotWidget::~PlotWidget()
|
|||
|
{
|
|||
|
delete m_customPlot;
|
|||
|
delete m_label_left;
|
|||
|
delete m_label_right;
|
|||
|
delete m_lineEdit_left;
|
|||
|
delete m_lineEdit_right;
|
|||
|
}
|
|||
|
|
|||
|
void PlotWidget::show_min_point_text(double x_min, double y_min)
|
|||
|
{
|
|||
|
if(m_count_graph>0)
|
|||
|
{
|
|||
|
m_minValueText->setText(QString("峰信息:\n焓值:\n峰值:%1\n起始点:\n终止点:").arg(x_min));///.arg(y_min));
|
|||
|
m_minValueText->setPen(QPen(Qt::green)); //字体颜色
|
|||
|
m_minValueText->setColor(Qt::green);
|
|||
|
m_minValueText->setVisible(true);
|
|||
|
m_minValueText->setSelectable(true);
|
|||
|
|
|||
|
///m_minValueText->setFlag(QCPItemText::ItemIsMovable);
|
|||
|
///m_minValueText->setMovable(true);
|
|||
|
m_minValueText->position->setCoords(x_min, y_min);
|
|||
|
m_customPlot->replot();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void PlotWidget::plot_connect_line(QVariant varx, QVariant vary)
|
|||
|
{
|
|||
|
if(m_count_graph>0)
|
|||
|
{
|
|||
|
QPen graphPen;
|
|||
|
graphPen.setColor(QColor(40, 255, 110, 250));
|
|||
|
graphPen.setWidthF(3.0);
|
|||
|
m_customPlot->addGraph();
|
|||
|
m_customPlot->graph()->setPen(graphPen);
|
|||
|
m_customPlot->graph()->setBrush(QBrush(QColor(0, 0, 255, 60)));
|
|||
|
///m_customPlot->graph()->setBrush(Qt::NoBrush);
|
|||
|
|
|||
|
QVector<double> vx1 = varx.value< QVector<double> >();
|
|||
|
QVector<double> vy1 = vary.value< QVector<double> >();
|
|||
|
|
|||
|
m_count_graph++;
|
|||
|
m_customPlot->graph(m_count_graph)->setData(vx1, vy1);
|
|||
|
m_customPlot->graph(m_count_graph)->setChannelFillGraph(m_customPlot->graph(m_count_graph-1));
|
|||
|
m_customPlot->legend->setVisible(false);
|
|||
|
m_customPlot->legend->setSelectableParts(QCPLegend::spItems);
|
|||
|
m_customPlot->axisRect()->setupFullAxesBox(true);
|
|||
|
m_customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom| QCP::iSelectAxes | QCP::iSelectLegend | QCP::iSelectPlottables | QCP::iMultiSelect | QCP::iSelectItems);
|
|||
|
|
|||
|
m_customPlot->replot();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void PlotWidget::save_sample_quality_area_data()
|
|||
|
{
|
|||
|
m_xlsx->addSheet(g_sname_string);
|
|||
|
m_xlsx->setColumnWidth(1,4);//第1行,6列宽
|
|||
|
m_xlsx->write(1,1, g_sname_string);
|
|||
|
m_xlsx->write(1,2, g_quality);
|
|||
|
m_xlsx->write(1,3, g_area);
|
|||
|
m_xlsx->write(1,4, g_target_x1);
|
|||
|
m_xlsx->saveAs(QDir::currentPath() + "/sample.ana");
|
|||
|
QMessageBox::information(this,"提示","保存成功!");
|
|||
|
}
|
|||
|
|
|||
|
void PlotWidget::clear_all_graph()
|
|||
|
{
|
|||
|
int count=m_customPlot->graphCount();//获取曲线条数
|
|||
|
// for(int i=1;i<count;i++)
|
|||
|
// {
|
|||
|
// m_customPlot->removeGraph(i);
|
|||
|
// }
|
|||
|
for(int i=count-1;i>=1;i--)
|
|||
|
{
|
|||
|
m_customPlot->removeGraph(i);
|
|||
|
}
|
|||
|
m_minValueText->setVisible(false);
|
|||
|
|
|||
|
if(1==count) m_clear_button->setDisabled(true);
|
|||
|
|
|||
|
m_lineLV->setVisible(false);
|
|||
|
m_lineRV->setVisible(false);
|
|||
|
|
|||
|
m_count_graph = 0;
|
|||
|
m_customPlot->replot();
|
|||
|
}
|
|||
|
|
|||
|
void PlotWidget::selectionChanged()
|
|||
|
{
|
|||
|
// synchronize selection of graphs with selection of corresponding legend items:
|
|||
|
for (int i=0; i<m_customPlot->graphCount(); ++i)
|
|||
|
{
|
|||
|
QCPGraph *graph = m_customPlot->graph(i);
|
|||
|
QCPPlottableLegendItem *item = m_customPlot->legend->itemWithPlottable(graph);
|
|||
|
if (item->selected() || graph->selected())
|
|||
|
{
|
|||
|
item->setSelected(true);
|
|||
|
//注意:这句需要Qcustomplot2.0系列版本
|
|||
|
graph->setSelection(QCPDataSelection(graph->data()->dataRange()));
|
|||
|
//这句1.0系列版本即可
|
|||
|
///graph->setSelected(true);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void PlotWidget::replot_xlsx_data()
|
|||
|
{
|
|||
|
// The following plot setup is mostly taken from the plot demos:
|
|||
|
QPen graphPen;
|
|||
|
///graphPen.setColor(QColor(std::rand()%245+10, std::rand()%245+10, std::rand()%245+10));
|
|||
|
graphPen.setColor(QColor(130, 40, 160));
|
|||
|
graphPen.setWidthF(2.0);
|
|||
|
|
|||
|
m_customPlot->addGraph();
|
|||
|
///m_customPlot->graph()->setPen(QPen(Qt::blue));
|
|||
|
m_customPlot->graph()->setPen(graphPen);
|
|||
|
///m_customPlot->graph()->setBrush(QBrush(QColor(0, 0, 255, 20)));
|
|||
|
m_customPlot->graph()->setBrush(Qt::NoBrush);
|
|||
|
|
|||
|
mutex.lock();
|
|||
|
if(slist_temper.size()!=slist_dsc.size()) return;
|
|||
|
QVector<double> x(slist_temper.size()), y0(slist_dsc.size());
|
|||
|
for(int i = 0; i < slist_temper.size(); ++i) {
|
|||
|
///qDebug() << slist_temper.at(i).toDouble()<<Qt::endl;
|
|||
|
x[i] = slist_temper.at(i).toDouble();
|
|||
|
}
|
|||
|
for (int j = 0; j < slist_dsc.size(); ++j) {
|
|||
|
///qDebug() << slist_dsc.at(j).toDouble()<<Qt::endl;
|
|||
|
y0[j] = slist_dsc.at(j).toDouble();
|
|||
|
///qDebug() << y0[j] <<Qt::endl;
|
|||
|
}
|
|||
|
mutex.unlock();
|
|||
|
|
|||
|
m_count_graph++;
|
|||
|
|
|||
|
m_customPlot->graph(m_count_graph)->setData(x, y0);
|
|||
|
m_customPlot->graph(m_count_graph)->rescaleAxes(); //适应图形比例
|
|||
|
///m_customPlot->graph(3)->setData(x, y1);
|
|||
|
m_customPlot->axisRect()->setupFullAxesBox(true);
|
|||
|
m_customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom| QCP::iSelectAxes | QCP::iSelectLegend | QCP::iSelectPlottables | QCP::iMultiSelect | QCP::iSelectItems);
|
|||
|
m_customPlot->replot();
|
|||
|
|
|||
|
m_clear_button->setDisabled(false);
|
|||
|
emit calcu_button_enable();
|
|||
|
}
|
|||
|
|
|||
|
void PlotWidget::setupPlot()
|
|||
|
{
|
|||
|
m_minValueText = new QCPItemText(m_customPlot);
|
|||
|
///minValueText->setLayer("overlay");
|
|||
|
m_minValueText->setText("峰值");
|
|||
|
m_minValueText->setVisible(false);
|
|||
|
m_minValueText->setSelectable(true);
|
|||
|
|
|||
|
///m_minValueText->position->setCoords( , );
|
|||
|
|
|||
|
m_tracer = new QCPItemTracer(m_customPlot); //初始化锚点
|
|||
|
m_tracer->setInterpolating(false);
|
|||
|
m_tracer->setStyle(QCPItemTracer::tsCircle);
|
|||
|
m_tracer->setPen(QPen(Qt::red));
|
|||
|
m_tracer->setBrush(Qt::red);
|
|||
|
m_tracer->setSize(6);
|
|||
|
m_tracer->setVisible(false);
|
|||
|
|
|||
|
|
|||
|
// The following plot setup is mostly taken from the plot demos:
|
|||
|
m_customPlot->addGraph();
|
|||
|
m_customPlot->graph()->setPen(QPen(Qt::green));
|
|||
|
m_customPlot->graph()->setBrush(QBrush(QColor(0, 0, 255, 20)));
|
|||
|
|
|||
|
QVector<double> x(500), y0(500), y1(500);
|
|||
|
|
|||
|
for (int i=0; i<500; ++i)
|
|||
|
{
|
|||
|
x[i] = (i/499.0-0.5)*1000;
|
|||
|
y0[i] = qExp(-x[i]*x[i]*0.25)*qSin(x[i]*5)*50;
|
|||
|
y1[i] = qExp(-x[i]*x[i]*0.25)*50;
|
|||
|
}
|
|||
|
|
|||
|
m_customPlot->graph(0)->setData(x, y0);
|
|||
|
m_customPlot->legend->setVisible(false);
|
|||
|
m_customPlot->legend->setSelectableParts(QCPLegend::spItems);
|
|||
|
m_customPlot->axisRect()->setupFullAxesBox(true);
|
|||
|
m_customPlot->xAxis->setLabel("Temp");
|
|||
|
m_customPlot->yAxis->setLabel("DSC");
|
|||
|
m_customPlot->xAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);//x轴终点箭头图案
|
|||
|
m_customPlot->xAxis->setLowerEnding(QCPLineEnding::esDisc); //x轴起点圆点图案
|
|||
|
m_customPlot->yAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);//y轴终点小方块图案
|
|||
|
m_customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom| QCP::iSelectAxes | QCP::iSelectLegend | QCP::iSelectPlottables | QCP::iMultiSelect | QCP::iSelectItems);
|
|||
|
|
|||
|
///m_customPlot->clearGraphs();
|
|||
|
for (int i=0; i< m_customPlot->graphCount(); ++i)
|
|||
|
{
|
|||
|
QCPGraph *graphItem = m_customPlot->graph(i);
|
|||
|
|
|||
|
///if (graphItem->selected())
|
|||
|
///{
|
|||
|
graphItem->setVisible(false);
|
|||
|
///}
|
|||
|
}
|
|||
|
|
|||
|
m_customPlot->replot();
|
|||
|
}
|
|||
|
|
|||
|
void PlotWidget::show_line_cursor()
|
|||
|
{
|
|||
|
m_lineLV->setVisible(true);
|
|||
|
m_lineRV->setVisible(true);
|
|||
|
m_customPlot->replot();
|
|||
|
}
|
|||
|
|
|||
|
void PlotWidget::hide_line_cursor()
|
|||
|
{
|
|||
|
m_lineLV->setVisible(false);
|
|||
|
m_lineRV->setVisible(false);
|
|||
|
m_customPlot->replot();
|
|||
|
}
|
|||
|
/*******************
|
|||
|
* @author xxx
|
|||
|
* @method
|
|||
|
* @param
|
|||
|
* 初始化游标
|
|||
|
*******************/
|
|||
|
void PlotWidget::plotWaterfall()
|
|||
|
{
|
|||
|
try {
|
|||
|
//默认曲线选择
|
|||
|
///graph = customPlot->graph(0);
|
|||
|
///graph = ui->plot->graph();
|
|||
|
|
|||
|
//设置游标初始位置(可以不设置)
|
|||
|
///QCPRange keyRange = customPlot->axisRect()->axis(QCPAxis::atBottom)->range();
|
|||
|
QCPRange keyRange = m_customPlot->axisRect()->axis(QCPAxis::atBottom)->range();
|
|||
|
// xValue1 = keyRange.upper * 0.2;
|
|||
|
// xValue2 = keyRange.upper * 0.7;
|
|||
|
xValue1 = keyRange.upper * 80;
|
|||
|
xValue2 = keyRange.upper * 102;
|
|||
|
QCPRange keyRange2 = m_customPlot->axisRect()->axis(QCPAxis::atLeft)->range();
|
|||
|
yValue = keyRange2.lower;
|
|||
|
auto iter1 = m_customPlot->graph()->data()->findBegin(xValue1);
|
|||
|
xValue1 = iter1->mainKey();
|
|||
|
auto iter2 = m_customPlot->graph()->data()->findBegin(xValue2);
|
|||
|
xValue2 = iter2->mainKey();
|
|||
|
|
|||
|
//左游标
|
|||
|
QPen pen(Qt::red,1.5,Qt::SolidLine); //颜色 、宽度、样式(直线)
|
|||
|
m_lineLV = new QCPItemStraightLine(m_customPlot);
|
|||
|
m_lineLV->setLayer("overlay");
|
|||
|
m_lineLV->setPen(pen);//设置游标线的样式
|
|||
|
m_lineLV->setClipToAxisRect(true);//自适应范围
|
|||
|
m_lineLV->point1->setCoords(xValue1, keyRange.upper);//起点坐标
|
|||
|
///m_lineLV->point2->setCoords(xValue1, 1);//终点坐标
|
|||
|
m_lineLV->point2->setCoords(xValue1, 1);//终点坐标
|
|||
|
m_lineLV->setVisible(false);
|
|||
|
|
|||
|
//右游标
|
|||
|
///QPen penr(Qt::green,1.5,Qt::SolidLine); //颜色 、宽度、样式(直线)
|
|||
|
m_lineRV = new QCPItemStraightLine(m_customPlot);
|
|||
|
m_lineRV->setLayer("overlay");
|
|||
|
m_lineRV->setPen(pen);
|
|||
|
m_lineRV->setClipToAxisRect(true);
|
|||
|
m_lineRV->point1->setCoords(xValue2, keyRange.lower);
|
|||
|
m_lineRV->point2->setCoords(xValue2, 1);
|
|||
|
m_lineRV->setVisible(false);
|
|||
|
|
|||
|
//编辑框显示初始位置
|
|||
|
m_lineEdit_left->setText(QString::number(m_lineLV->point1->key()));
|
|||
|
m_lineEdit_right->setText(QString::number(m_lineRV->point1->key()));
|
|||
|
|
|||
|
m_customPlot->replot();
|
|||
|
} catch (...) {
|
|||
|
qDebug("游标初始化异常!");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*******************
|
|||
|
* @author xxx
|
|||
|
* @method
|
|||
|
* @param
|
|||
|
* 鼠标抓取事件 点击曲线游标显示
|
|||
|
*******************/
|
|||
|
void PlotWidget::mousePress(QMouseEvent *event)
|
|||
|
{
|
|||
|
try {
|
|||
|
|
|||
|
QCPGraph *tmGraph = m_customPlot->graph(0);
|
|||
|
//得到锚点的像素坐标
|
|||
|
QPointF temp = m_tracer->position->coords();
|
|||
|
//将像素点转换成qcustomplot中的坐标值,并通过setGraphKey将锚点值设为真实数据值。
|
|||
|
m_tracer->setGraphKey(m_customPlot->xAxis->pixelToCoord(event->pos().x()));
|
|||
|
//遍历曲线
|
|||
|
for (int i = 0; i < m_customPlot->graphCount(); ++i)
|
|||
|
{
|
|||
|
//判断哪一条曲线被选中
|
|||
|
if(m_customPlot->graph(i)->selected())
|
|||
|
{
|
|||
|
//显示锚点
|
|||
|
m_tracer->setVisible(true);
|
|||
|
tmGraph = m_customPlot->graph(i);
|
|||
|
//显示tip框
|
|||
|
///QToolTip::showText(event->globalPos(), tr( "<h4>%L1</h4>"
|
|||
|
///QToolTip::showText(QCursor::pos(), tr( "<h4>%L1</h4>"
|
|||
|
QToolTip::showText(QCursor::pos(), tr("<table>"
|
|||
|
"<tr>"
|
|||
|
"<td><h5>X: %L1</h5></td>" "<td> , </td>" "<td><h5>Y: %L2</h5></td>"
|
|||
|
"</tr>"
|
|||
|
"</table>").
|
|||
|
arg( QString::number( temp.x(), 'g' ) )
|
|||
|
.arg( QString::number( temp.y(), 'g' ) ),
|
|||
|
this, this->rect());
|
|||
|
break;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//没有曲线被选中,不显示锚点
|
|||
|
m_tracer->setVisible(false);
|
|||
|
}
|
|||
|
}
|
|||
|
//将锚点设置到被选中的曲线上
|
|||
|
m_tracer->setGraph(tmGraph);
|
|||
|
//重绘
|
|||
|
m_customPlot->replot();
|
|||
|
|
|||
|
//定义鼠标距离游标的像素距离
|
|||
|
double distanceLV = m_lineLV->selectTest(event->pos(), false);
|
|||
|
double distanceRV = m_lineRV->selectTest(event->pos(), false);
|
|||
|
///double distanceH = m_lineH->selectTest(event->pos(), false);
|
|||
|
|
|||
|
//定义游标标识,由上面的距离来决定移动那根游标
|
|||
|
if (event->button() == Qt::RightButton && distanceLV <= 5 && m_customPlot->axisRect()->rect().contains(event->pos())){
|
|||
|
lLineV = true;
|
|||
|
}
|
|||
|
if (event->button() == Qt::RightButton && distanceRV <= 5 && m_customPlot->axisRect()->rect().contains(event->pos())){
|
|||
|
rLineV = true;
|
|||
|
}
|
|||
|
|
|||
|
//左右游标重合时,先移动右游标(非必须)
|
|||
|
if(event->button() == Qt::RightButton){//鼠标右键判断
|
|||
|
if(m_customPlot->axisRect()->rect().contains(event->pos())){//鼠标点在图像内
|
|||
|
if(distanceLV <= 5 && distanceRV <= 5){//重合时
|
|||
|
//这里获取曲线的最后一个值,以判断重合位置是否在末尾,如果是则先移动左游标,否则都先移动右游标
|
|||
|
///double end = tempXpoinLists[subscript].last();
|
|||
|
double end = m_lineRV->point1->key();
|
|||
|
double now = m_lineLV->point1->key();
|
|||
|
if(now == end){
|
|||
|
lLineV = true;
|
|||
|
rLineV = false;
|
|||
|
}else{
|
|||
|
lLineV = false;
|
|||
|
rLineV = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
m_customPlot->replot();
|
|||
|
} catch (...) {
|
|||
|
qDebug("系统发异常!");
|
|||
|
}
|
|||
|
}
|
|||
|
/*******************
|
|||
|
* @author xxx
|
|||
|
* @method
|
|||
|
* @param
|
|||
|
* 游标移动
|
|||
|
*******************/
|
|||
|
void PlotWidget::mouseMove(QMouseEvent *event)
|
|||
|
{
|
|||
|
try{
|
|||
|
|
|||
|
|
|||
|
//当前鼠标位置(像素坐标)
|
|||
|
double x_pos = event->pos().x();
|
|||
|
///double y_pos = event->pos().y();
|
|||
|
|
|||
|
//像素坐标转成实际的x,y轴的坐标
|
|||
|
double x_val = m_customPlot->xAxis->pixelToCoord(x_pos);
|
|||
|
///double y_val = m_customPlot->yAxis->pixelToCoord(y_pos);
|
|||
|
|
|||
|
//获取当前曲线上最近的X轴点坐标
|
|||
|
if(m_count_graph<=1)
|
|||
|
{
|
|||
|
auto iter = m_customPlot->graph(m_count_graph)->data()->findBegin(x_val);
|
|||
|
x_val = iter->mainKey();
|
|||
|
}
|
|||
|
if(m_count_graph>1)
|
|||
|
{
|
|||
|
auto iter = m_customPlot->graph(1)->data()->findBegin(x_val);
|
|||
|
x_val = iter->mainKey();
|
|||
|
}
|
|||
|
//获取当前游标X轴的坐标
|
|||
|
double r_point = m_lineRV->point1->key();
|
|||
|
double l_point = m_lineLV->point1->key();
|
|||
|
//获取距离
|
|||
|
double distanceLV = m_lineLV->selectTest(event->pos(), false);
|
|||
|
double distanceRV = m_lineRV->selectTest(event->pos(), false);
|
|||
|
|
|||
|
//当鼠标在游标上时改变鼠标形状
|
|||
|
if (distanceLV <= 5 || distanceRV <= 5){// || distanceH <= 5 && ui->plot->axisRect()->rect().contains(event->pos())){
|
|||
|
m_customPlot->setCursor(Qt::ClosedHandCursor);
|
|||
|
}else{
|
|||
|
m_customPlot->setCursor(Qt::ArrowCursor);
|
|||
|
}
|
|||
|
|
|||
|
//游标移动判断
|
|||
|
if(lLineV)
|
|||
|
{//移动左游标
|
|||
|
if(x_val > r_point){ //跟右游标左判断,限制边界
|
|||
|
m_lineLV->point1->setCoords(r_point, m_customPlot->yAxis->range().lower);
|
|||
|
m_lineLV->point2->setCoords(r_point, m_customPlot->yAxis->range().upper);
|
|||
|
}else {
|
|||
|
m_lineLV->point1->setCoords(x_val, m_customPlot->yAxis->range().lower);
|
|||
|
m_lineLV->point2->setCoords(x_val, m_customPlot->yAxis->range().upper);
|
|||
|
}
|
|||
|
m_lineEdit_left->setText(QString::number(m_lineLV->point1->key()));
|
|||
|
m_customPlot->replot();
|
|||
|
}
|
|||
|
if(rLineV)
|
|||
|
{
|
|||
|
if (x_val < l_point) {
|
|||
|
m_lineRV->point1->setCoords(l_point, m_customPlot->yAxis->range().lower);
|
|||
|
m_lineRV->point2->setCoords(l_point, m_customPlot->yAxis->range().upper);
|
|||
|
}
|
|||
|
else {
|
|||
|
m_lineRV->point1->setCoords(x_val, m_customPlot->yAxis->range().lower);
|
|||
|
m_lineRV->point2->setCoords(x_val, m_customPlot->yAxis->range().upper);
|
|||
|
}
|
|||
|
m_lineEdit_right->setText(QString::number(m_lineRV->point1->key()));
|
|||
|
m_customPlot->replot();
|
|||
|
}
|
|||
|
//进行相应的计算
|
|||
|
if(lLineV || rLineV || bLineH){
|
|||
|
// calculate_integral();
|
|||
|
// calculate_average();
|
|||
|
}
|
|||
|
} catch (...) {
|
|||
|
qDebug("系统发异常!");
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
/**
|
|||
|
* @brief Average::mouseRelease
|
|||
|
* @param e
|
|||
|
* 鼠标释放事件 关闭游标移动
|
|||
|
*/
|
|||
|
void PlotWidget::mouseRelease()
|
|||
|
{
|
|||
|
lLineV = false;
|
|||
|
rLineV = false;
|
|||
|
bLineH = false;
|
|||
|
}
|
|||
|
|
|||
|
void PlotWidget::get_coordinate_calcu()
|
|||
|
{
|
|||
|
mutex.lock();
|
|||
|
if(slist_temper.size()!=slist_dsc.size()) return;
|
|||
|
QMap<double, double> dd_map;
|
|||
|
QVector<double> x(slist_temper.size()), y0(slist_dsc.size());
|
|||
|
for(int i = 0; i < slist_temper.size(); ++i) {
|
|||
|
///qDebug() << slist_temper.at(i).toDouble()<<Qt::endl;
|
|||
|
x[i] = slist_temper.at(i).toDouble();
|
|||
|
}
|
|||
|
for (int j = 0; j < slist_dsc.size(); ++j) {
|
|||
|
///qDebug() << slist_dsc.at(j).toDouble()<<Qt::endl;
|
|||
|
y0[j] = slist_dsc.at(j).toDouble();
|
|||
|
}
|
|||
|
for (int t = 0; t < slist_dsc.size(); ++t) {
|
|||
|
///qDebug() << slist_dsc.at(j).toDouble()<<Qt::endl;
|
|||
|
dd_map.insert(x[t], y0[t]);
|
|||
|
}
|
|||
|
///slist_temper.clear();
|
|||
|
///slist_dsc.clear();
|
|||
|
mutex.unlock();
|
|||
|
|
|||
|
double x1 = m_lineLV->point1->key(); //左选线横轴坐标值
|
|||
|
double x2 = m_lineRV->point1->key(); //右选线横轴坐标值
|
|||
|
double y1 = dd_map.value(x1);
|
|||
|
double y2 = dd_map.value(x2);
|
|||
|
double k = (y2-y1)*1.0/(x2-x1);
|
|||
|
double b = y1-k*x1;
|
|||
|
|
|||
|
//1、获取两游标当前的坐标点
|
|||
|
int begin = 0, end = 0;
|
|||
|
double r_point = m_lineRV->point1->key();
|
|||
|
double l_point = m_lineLV->point1->key();
|
|||
|
//2、根据坐标点找到曲线中对应的数据点位置 begin是曲线中第一个点位置 end是最后一个点位置
|
|||
|
for (int i = 0; i < x.length(); ++i) {
|
|||
|
if(x[i] == l_point){
|
|||
|
begin = i;
|
|||
|
}
|
|||
|
if(x[i] == r_point){
|
|||
|
end = i;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
int n = end-begin+1;
|
|||
|
QVector<double> x_1(n), y_1(n);
|
|||
|
for (int i = 0; i < n; i++) {
|
|||
|
x_1[i] = x[begin+i];
|
|||
|
y_1[i] = k*x[begin+i]+b;
|
|||
|
}
|
|||
|
QVariant dataVarx,dataVary;
|
|||
|
dataVarx.setValue(x_1);
|
|||
|
dataVary.setValue(y_1);
|
|||
|
|
|||
|
emit send_line_data_to_plot(dataVarx,dataVary);
|
|||
|
|
|||
|
|
|||
|
//采用的是梯形计算法,也可以采用积分等面积算法进行计算
|
|||
|
//根据这两个点位置区间计算所有的形成梯形面积 面积公式:(上底 + 下底)* 高 / 2;
|
|||
|
double upper; //上底
|
|||
|
double lower; //下底
|
|||
|
double high; //高
|
|||
|
double area = 0; //面积
|
|||
|
for (int i = begin; i < end; ++i) {
|
|||
|
upper = k*x[i]+b-y0[i];
|
|||
|
lower = k*x[i+1]+b-y0[i+1];
|
|||
|
high = x[i+1] - x[i];
|
|||
|
area += (upper+ lower)*high / 2;
|
|||
|
}
|
|||
|
qDebug() << "caculate area"<< area <<Qt::endl;
|
|||
|
g_area = area;
|
|||
|
|
|||
|
|
|||
|
//求解切线,由最低点分两段计算
|
|||
|
double ymin=100.0;
|
|||
|
int middle = 0;
|
|||
|
for (int j = begin; j < end-1; j++)
|
|||
|
{
|
|||
|
if(y0[j]<ymin)
|
|||
|
{
|
|||
|
ymin = y0[j];
|
|||
|
middle = j;
|
|||
|
}
|
|||
|
}
|
|||
|
emit show_min_point(x[middle], y0[middle]);
|
|||
|
///QMap<double, double> qm_kb;
|
|||
|
double k1;
|
|||
|
double b1;
|
|||
|
double kmin = 0.0;
|
|||
|
double kmax = -10000.0;
|
|||
|
double b_tang1 = 0.0;
|
|||
|
int tangp1 = 0, tangp2 = 0;
|
|||
|
for (int j = begin+4; j < middle-4; j++)
|
|||
|
{
|
|||
|
k1= (y0[j+4]-y0[j-4])/(x[j+4]-x[j-4]);
|
|||
|
b1 =y0[j]-k1*x[j];
|
|||
|
if(k1 < kmin)
|
|||
|
{
|
|||
|
kmin = k1;
|
|||
|
tangp1 = j;
|
|||
|
b_tang1 = b1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
g_kmin = kmin;
|
|||
|
g_b_tang1 = b_tang1;
|
|||
|
///emit show_tang();
|
|||
|
QString expression1 = QString("y=%1 * x + %2").arg(kmin).arg(b_tang1);
|
|||
|
qDebug()<<"切线表达式1: "<<expression1;
|
|||
|
qDebug()<<"左切点坐标: "<<x[tangp1] <<","<< y0[tangp1]<<Qt::endl;
|
|||
|
double x_tang_1 = x[tangp1];
|
|||
|
double y_tang_1 = y0[tangp1];
|
|||
|
double x_tang_2 = m_lineLV->point1->key();
|
|||
|
double y_tang_2 = kmin*x_tang_2+b_tang1;
|
|||
|
|
|||
|
double x_conn_3 = m_lineLV->point1->key(); //左选线横轴坐标值
|
|||
|
double y_conn_3 = dd_map.value(x1);
|
|||
|
double x_conn_4 = m_lineRV->point1->key(); //右选线横轴坐标值
|
|||
|
double y_conn_4 = dd_map.value(x2);
|
|||
|
|
|||
|
///Point p1,p2,p3,p4;对应的四个点,根据实际应用场景赋值
|
|||
|
double a1, a2, a3, c1, c2, c3;
|
|||
|
double t, target_x, target_y;
|
|||
|
a1 = y_conn_4 - y_conn_3;
|
|||
|
a2 = y_conn_3 - y_tang_1;
|
|||
|
a3 = y_tang_2 - y_tang_1;
|
|||
|
c1 = x_conn_4 - x_conn_3;
|
|||
|
c2 = x_conn_3 - x_tang_1;
|
|||
|
c3 = x_tang_2 - x_tang_1;
|
|||
|
t = (a3 * c2 - a2 * c3) / (a1 * c3 - a3 * c1);
|
|||
|
target_x = (x_conn_4 - x_conn_3) * t + x_conn_3;
|
|||
|
target_y = (y_conn_4- y_conn_3) * t + y_conn_3;
|
|||
|
|
|||
|
g_target_x1 = target_x;
|
|||
|
g_target_y1 = target_y;
|
|||
|
|
|||
|
qDebug()<<"两直线交点坐标1: "<<target_x <<","<< target_y<<Qt::endl;
|
|||
|
|
|||
|
double k2;
|
|||
|
double b2;
|
|||
|
double b_tang2=0.0;
|
|||
|
for (int t = middle; t < end-1; t++)
|
|||
|
{
|
|||
|
k2= (y0[t+1]-y0[t-1])/(x[t+1]-x[t-1]);
|
|||
|
b2 =y0[t]-k2*x[t];
|
|||
|
if(k2 > kmax)
|
|||
|
{
|
|||
|
kmax = k2;
|
|||
|
tangp2 = t;
|
|||
|
b_tang2 = b2;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
g_kmax = kmax;
|
|||
|
g_b_tang2 = b_tang2;
|
|||
|
|
|||
|
double x_tang_11 = x[tangp2];
|
|||
|
double y_tang_11 = y0[tangp2];
|
|||
|
double x_tang_22 = m_lineRV->point1->key();
|
|||
|
double y_tang_22 = kmax*x_tang_22+b_tang2;
|
|||
|
|
|||
|
double x_conn_33 = m_lineLV->point1->key(); //左选线横轴坐标值
|
|||
|
double y_conn_33 = dd_map.value(x1);
|
|||
|
double x_conn_44 = m_lineRV->point1->key(); //右选线横轴坐标值
|
|||
|
double y_conn_44 = dd_map.value(x2);
|
|||
|
|
|||
|
///Point p1,p2,p3,p4;对应的四个点,根据实际应用场景赋值
|
|||
|
double a11, a22, a33, c11, c22, c33;
|
|||
|
double t2, target_x2, target_y2;
|
|||
|
a11 = y_conn_44 - y_conn_33;
|
|||
|
a22 = y_conn_33 - y_tang_11;
|
|||
|
a33 = y_tang_22 - y_tang_11;
|
|||
|
c11 = x_conn_44 - x_conn_33;
|
|||
|
c22 = x_conn_33 - x_tang_11;
|
|||
|
c33 = x_tang_22 - x_tang_11;
|
|||
|
t2 = (a33 * c22 - a22 * c33) / (a11 * c33 - a33 * c11);
|
|||
|
target_x2 = (x_conn_44 - x_conn_33) * t2 + x_conn_33;
|
|||
|
target_y2 = (y_conn_44- y_conn_33) * t2 + y_conn_33;
|
|||
|
|
|||
|
g_target_x2 = target_x2;
|
|||
|
g_target_y2 = target_y2;
|
|||
|
|
|||
|
qDebug()<<"两直线交点坐标2: "<<target_x2 <<","<< target_y2<<Qt::endl;
|
|||
|
emit show_area();
|
|||
|
emit show_tang();
|
|||
|
///emit show_connect_line(x1, y1, x2, y2);
|
|||
|
|
|||
|
QString expression2 = QString("y=%1 * x + %2").arg(kmax).arg(b_tang2);
|
|||
|
qDebug()<<"切线表达式2: "<<expression2;
|
|||
|
|
|||
|
qDebug() << "begin"<< begin << "middle"<< middle << "end"<< end <<Qt::endl;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|