DSCAnalysisTool/YT_TANGOUS_Release/plotwidget.cpp
2025-03-06 15:25:37 +08:00

730 lines
25 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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