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