DSCAnalysisTool/YT_TANGOUS_Release/plotwidget.cpp

730 lines
25 KiB
C++
Raw Normal View History

2025-03-06 07:25:37 +00:00
#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;
}