logplus/logPlus/LogmudItemDrawer.cpp

3093 lines
146 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.

#pragma warning(push,0)
#include <QPainter>
#include <QtDebug>
#include <QGraphicsWidget>
#include <QGraphicsView>
#include <QStyleOptionGraphicsItem>
#include "LogmudItemDrawer.h"
#include <QtSvg/QSvgRenderer>
#include <QtGlobal>
#include <float.h>
#include "geometryutils.h"
#pragma warning(pop)
extern double g_dPixelPerCm;//每厘米像素数
LogmudItemDrawer::LogmudItemDrawer()
{
m_pViewInfoLogmud = new ViewInfoLogmud;
}
QPointF LogmudItemDrawer::DrawItem(QPainter* painter, LogmudResultItem* item,
const QRectF& tmprt,
bool IsWellSectonHorizonLayout ) const
{
float dd=0;
QPointF pt;
LogmudResultItem* resultitem = item;
if(resultitem != NULL)
{
//CObjLogmudResult *pCore = dynamic_cast<CObjLogmudResult *>(m_NodeBuilder->GetOSGObject());
QRectF rt=tmprt;//viewInfoItem.rect;// 获取绘图区域矩形
QPointF pt1(rt.x()+rt.width()*0.5,rt.center().y());
QPointF pt2(rt.x()+rt.width()*0.5,rt.center().y()-resultitem->GetNumber()/2);
QPointF pt3(rt.x()+rt.width()*0.5,rt.center().y()+5.0);
float lscalelen=0;
painter->save();// 保存当前绘图状态,以便后面恢复
QFont font("黑体", 10);// =m_pSceneManager->GetZoomedFont(m_pViewInfoLogmud->GetLogScaleFont());
painter->setFont(font);
pt1=painter->transform().map(pt1);// 将点转换到当前坐标系
pt2=painter->transform().map(pt2);
pt3=painter->transform().map(pt3);
//pCore->m_R=(pt3.y()-pt1.y())/5.0/m_pSceneManager->GetCoordinate()->GetPixelPerCm();// 计算半径
rt=painter->transform().mapRect(rt);
QRectF rc=painter->transform().mapRect(rc); // 将矩形rc转换到当前坐标系
QTransform transform;
transform.reset();
painter->setWorldTransform(transform);
QFont ft("黑体", 13);// = GetSceneManager()->GetZoomedFont(m_pViewInfoLogmud->GetFont());// 获取缩放后的字体
painter->setFont(ft);
QFontMetrics fm(ft);
if(m_isOneScale||!m_bisHi){
dd=rt.width()*2.0/10;// 设置边距为宽度的20%
if(dd>1* g_dPixelPerCm) // 如果边距太大
dd=1* g_dPixelPerCm;
}
// else {
// dd=fm.height()*((pCore->GetFieldName().size()-1)*2+1);// 根据字段名数量计算边距
// }
//设置高度和设置画笔
float h = m_fHei;// m_pViewInfoLogmud->GetrHeight();
float timemin = m_fTimemin;// m_pViewInfoLogmud->GetTimeMin();// 获取时间最小值
float timemax = m_fTimemax;// m_pViewInfoLogmud->GetTimeMax();// 获取时间最大值
if(h<=0) h=1;
h*= g_dPixelPerCm;
QPen pen1=painter->pen();
QColor cl(0,0,0);
pen1.setColor(cl);
pen1.setWidth(1);
painter->setPen(pen1);
float len=0,w=0;
//开始绘制
{
painter->save();
pt=pt1;
len=rt.width()-2*dd;
w=len;
dd+=dd/2;
{
///刻度
int m_nLogarithmic=m_pViewInfoLogmud->GetLogarithmic();
//m_LeftVal=m_pViewInfoLogmud->GetPropertyMin();
//m_RightVal=m_pViewInfoLogmud->GetPropertyMax();
float lval=m_LeftVal;
if(m_nLogarithmic ==AXIS_LOGARITHMIC){
if(lval<=0) lval=0.1;
lval=log10(lval);
}
float rval=m_RightVal;
if(m_nLogarithmic ==AXIS_LOGARITHMIC)
{
if(m_RightVal<=0) rval=0.1;
rval=log10(rval);
}
if(lval==rval)
{
if(lval==0) rval=0.1;
else rval=10*lval;
}
//if(m_pViewInfoLogmud->GetTLogarithmic()) {
if(m_nTLogarithmic) {
if(timemin<=0) timemin=0.1;
if(timemax<=0) timemin=0.1;
if(timemin==timemax) timemax=timemin*10;
}
float dtime=timemax-timemin;
if(m_nTLogarithmic ==AXIS_LOGARITHMIC) {
dtime=log10(timemax)-log10(timemin);
}
if(dtime==0) dtime=1;
/////////////////
// 如果是3H图版类型
if(resultitem->type==1){
// 保存原始坐标系设置
int originalLogarithmic = m_pViewInfoLogmud->GetLogarithmic();
int originalTLogarithmic = m_pViewInfoLogmud->GetTLogarithmic();
// 临时设置为对数坐标系
m_pViewInfoLogmud->SetLogarithmic(AXIS_LOGARITHMIC); // 设置Y轴为对数坐标系
m_pViewInfoLogmud->SetTLogarithmic(AXIS_LOGARITHMIC); // 设置X轴为对数坐标系
//定义颜色和阈值
QColor _valueAreaColors[] = {
QColor(149,239,149),
QColor(107,154,238),
QColor(45,144,45),
QColor(253,144,10),
QColor(208,99,99)
};
double WhThreshes[] = { 0.5, 17.5, 40.0, 100.0 };
QString ValueAreaLabels[] = { "干气", "凝析气天然气", "凝析油", "", "氧化油" };
//painter->drawEllipse(pt1,30,30);
float a = (float)WhThreshes[0];
float b = (float)WhThreshes[1];
float c = (float)WhThreshes[2];
float d = (float)WhThreshes[3];
///刻度
//float m_LeftVal;//=pCore->m_LeftVals[k];
//float m_RightVal;//=pCore->m_RightVals[k];
int Logarithmic=m_pViewInfoLogmud->GetLogarithmic();
//m_LeftVal=m_pViewInfoLogmud->GetPropertyMin();
//m_RightVal=m_pViewInfoLogmud->GetPropertyMax();
timemin = 0.1f;
timemax = 1000.0f;
float m_LeftVal = 0.1f;
float m_RightVal = 10000.0f;
float lval=m_LeftVal;
if(Logarithmic==AXIS_LOGARITHMIC){
if(lval<=0) lval=0.1;
lval=log10(lval);
}
float rval=m_RightVal;
if(Logarithmic==AXIS_LOGARITHMIC)
{
if(m_RightVal<=0) rval=0.1;
rval=log10(rval);
}
if(lval==rval)
{
if(lval==0) rval=0.1;
else rval=10*lval;
}
if(m_pViewInfoLogmud->GetTLogarithmic()) {
if(timemin<=0) timemin=0.1;
if(timemax<=0) timemax=0.1;
if(timemin==timemax) timemax=timemin*10;
}
float dtime=timemax-timemin;
if(m_pViewInfoLogmud->GetTLogarithmic() ==AXIS_LOGARITHMIC) {
dtime=log10(timemax)-log10(timemin);
}
if(dtime==0) dtime=1;
if (resultitem->WH > timemax) {
// 将最大值扩展到下一个10的幂次方
timemax = pow(10, ceil(log10(resultitem->WH)));
}
// 检查Y轴 (BH值)
if (resultitem->BH > m_RightVal) {
// 将最大值扩展到下一个10的幂次方
m_RightVal = pow(10, ceil(log10(resultitem->BH)));
}
int fnum= m_xGrid;// 默认网格数为5
//fnum=m_pViewInfoLogmud->GetxGrid();
if(m_pViewInfoLogmud->GetTLogarithmic() ==AXIS_LOGARITHMIC)// 如果X轴是对数坐标系
{
DrawXAxisLogarithmicGrid(painter, timemin, timemax, dd, w, h, rt, pt, fm, lscalelen);
}
else //如果y轴是线性坐标系
{
DrawXAxisLinearGrid(painter, timemin, timemax, dd, len, h, rt, pt, pt1, fm, fnum);
}
//设置Y轴网格数和开始绘制Y轴对数网格
fnum = m_yGrid;// m_pViewInfoLogmud->GetyGrid();
if(m_pViewInfoLogmud->GetLogarithmic() ==AXIS_LOGARITHMIC) // 如果Y轴是对数坐标系
{
DrawYAxisLogarithmicGrid(painter, m_LeftVal, m_RightVal, dd, len, h, rt, pt, fm, lscalelen);
}
else // 如果Y轴是线性坐标系循环绘制fnum+1条网格线
{
DrawYAxisLinearGrid(painter, m_LeftVal, m_RightVal, dd, len, h, rt, pt, fm, lscalelen, fnum);
}
/// DRAW RECT
for(int m=0;m<5;m++){
int n=4;
QPointF Points[5];
if(m==0) {
QPointF Points1[] ={
QPointF(0.1f, 10000),
QPointF(a, 10000),
QPointF(a, 1000),
QPointF(0.1f, 1000),
};
for(int j=0;j<4;j++) Points[j]=Points1[j];
}
else if(m==1)
{
QPointF Points1[] ={
QPointF(a, 1000),
QPointF(d, 1000),
QPointF(d, 100),
QPointF(a, a),
};
for(int j=0;j<4;j++) Points[j]=(Points1[j]);
}
else if(m==2)
{
QPointF Points1[] ={
QPointF(b, b),
QPointF(b, a),
QPointF(a, a),
};
n=3;
for(int j=0;j<3;j++) Points[j]=(Points1[j]);
}
else if(m==3)
{
QPointF Points1[] ={
QPointF(b, b),
QPointF(c, c),
QPointF(c, a),
QPointF(b, a),
};
for(int j=0;j<4;j++) Points[j]=(Points1[j]);
}
else if(m==4)
{
QPointF Points1[] ={
QPointF(c, c),
QPointF(d, d),
QPointF(d, a),
QPointF(c, a),
};
for(int j=0;j<4;j++) Points[j]=(Points1[j]);
}
QVector<QPointF> points;
points.resize(n+1);
float yval=0;
int jj=0;
for(int j=0;j<n;j++)
{
if(Points[j].x()<timemin) continue;
if(Points[j].x()>timemax) continue;
if(m_pViewInfoLogmud->GetTLogarithmic() ==AXIS_LOGARITHMIC) // 如果X轴是对数坐标系
{
float val=Points[j].x();
if(val<=0) val=timemin;
points[jj].setX(rt.left()+dd+(log10(val)-log10(timemin))*len/dtime);// 计算对数x坐标
}
else {// 如果X轴是线性坐标系
points[jj].setX(rt.left()+dd+(Points[j].x()-timemin)*len/dtime);
}
if(Logarithmic==AXIS_LINEAR) {// 如果Y轴是线性坐标系
yval=(Points[j].y()-m_LeftVal)/(m_RightVal-m_LeftVal)*h;
}
else if(Logarithmic==AXIS_LOGARITHMIC) // 如果Y轴是对数坐标系
{
float val=Points[j].y();
if(val<=0) val=0.1;
yval=(log10(val)-lval)/(rval-lval)*h;
}
if(yval<0) yval=0;
if(yval>h) yval=h;
points[jj++].setY(pt1.y()+h-yval);
}
// 在循环前,定义每个区域标签的坐标(人工设置)
QPointF labelPositions[5] = {
QPointF(rt.left() + dd + len * (30.0/376.0), rt.top() + h * (20.0/187.0)), // m=0
QPointF(rt.left() + dd + len * (150.0/376.0), rt.top() + h * (75.0/187.0)), // m=1
QPointF(rt.left() + dd + len * (170.0/376.0), rt.top() + h * (145.0/187.0)), // m=2
QPointF(rt.left() + dd + len * (227.0/376.0), rt.top() + h * (135.0/187.0)), // m=3
QPointF(rt.left() + dd + len * (265.0/376.0), rt.top() + h * (130.0/187.0)) // m=4
};
//绘制多边形
if(jj>0){// 如果有有效点
// if(pCore->dotdeps.indexOf(resultitem->GetNumber()) < 0){
// pCore->dotdeps.append(resultitem->GetNumber());
// pCore->curves.append(points);
// }
painter->save();
QColor color=Qt::black;
QPen pPen=painter->pen();
pPen.setStyle(Qt::SolidLine);
float penw=GetLineWidth(painter,1);
if(penw<1) penw=1;
pPen.setWidthF(penw);
pPen.setColor(color);
painter->setPen(pPen);
painter->setBrush(_valueAreaColors[m]);
points[n]=(points[0]);
painter->drawPolygon(&points[0],jj+1);// 绘制多边形
// ★ 在这里加区域标签
QString label = ValueAreaLabels[m];
QFont font("Microsoft YaHei", 6);
painter->setFont(font);
QFontMetrics fm(font);
// 文字宽高
int textWidth = fm.width(label); // 老版本用 width()
int textHeight = fm.height();
// 偏移文字,使坐标为中心
QPointF centerPos = labelPositions[m];
QPointF drawPos(centerPos.x() - textWidth/2.0, centerPos.y());
painter->drawText(drawPos, label);
painter->restore();
}
}
painter->save();
painter->restore();
// 绘制投点
DrawDataPoint(painter, resultitem->WH, resultitem->BH, timemin, timemax,
m_LeftVal, m_RightVal, dd, len, h, rt, pt1, Logarithmic);
// 绘制深度和轴标题
DrawDepthAndAxisLabels(painter, resultitem->depth, dd, w, h, rt, pt, fm, lscalelen, "湿度比WH","平衡比BH");
// 绘制辅助线
painter->drawLine(QPointF(rt.left(), pt1.y()), QPointF(rt.left()+rt.width()/20, pt1.y()));
m_pViewInfoLogmud->SetLogarithmic(originalLogarithmic);
m_pViewInfoLogmud->SetTLogarithmic(originalTLogarithmic);
QImage image(400, 300, QImage::Format_RGB32);
// 用白色填充整个图像
image.fill(Qt::white);
QPainter pter(&image);
}//判断3H图版的右括号
//绘制对数图版
else if(resultitem->type==2){
// 保存原始坐标系设置
int originalLogarithmic = m_pViewInfoLogmud->GetLogarithmic();
int originalTLogarithmic = m_pViewInfoLogmud->GetTLogarithmic();
auto ClampPositiveFinite = [](float v, float minV, float maxV)->float
{
if(!IsFiniteNumber(v)||v<=minV) return minV;
if(v>maxV) return maxV;
return v;
};
float wh = ClampPositiveFinite(resultitem->WH,1.0f,1000000.0f);
float bh = ClampPositiveFinite(resultitem->BH,1.0f,1000000.0f);
// 临时设置为对数坐标系
m_pViewInfoLogmud->SetLogarithmic(AXIS_LOGARITHMIC); // 设置Y轴为对数坐标系
m_pViewInfoLogmud->SetTLogarithmic(AXIS_LOGARITHMIC); // 设置X轴为对数坐标系
//绘制对数图版
painter->save();
float timemin = 1.0f;
float timemax = 1000.0f;
float m_LeftVal = 1.0f;
float m_RightVal = 1000.0f;
if (wh > timemax) {
// 将最大值扩展到下一个10的幂次方
timemax = pow(10, ceil(log10(wh)));
}
// 检查Y轴 (BH值)
if (bh > m_RightVal) {
// 将最大值扩展到下一个10的幂次方
m_RightVal = pow(10, ceil(log10(bh)));
}
if(!IsFiniteNumber(timemax)||timemax<=timemin) timemax=1000.0f;
if(!IsFiniteNumber(m_RightVal)||m_RightVal<=m_LeftVal) m_RightVal=1000.0f;
float lval = m_LeftVal;
int Logarithmic = m_pViewInfoLogmud->GetLogarithmic();
if(Logarithmic == AXIS_LOGARITHMIC){
if(lval <= 0) lval = 0.1f;
lval = log10(lval);
}
float rval = m_RightVal;
if(Logarithmic == AXIS_LOGARITHMIC){
if(rval <= 0) rval = 0.1f;
rval = log10(rval);
}
// 重新计算X轴范围
float dtime = timemax - timemin;
if(m_pViewInfoLogmud->GetTLogarithmic() == AXIS_LOGARITHMIC) {
dtime = log10(timemax) - log10(timemin);
}
if(dtime == 0) dtime = 1;
// 定义区域标签
QString labelA = "A";
QString labelB = "B";
QString labelC = "C";
QString labelD = "D";
// 先绘制坐标系
int fnum=5;// 默认网格数为5
fnum=m_pViewInfoLogmud->GetxGrid();
DrawXAxisLogarithmicGrid(painter, timemin, timemax, dd, w, h, rt, pt, fm, lscalelen);
//设置Y轴网格数和开始绘制Y轴对数网格
fnum=m_pViewInfoLogmud->GetyGrid();
DrawYAxisLogarithmicGrid(painter, m_LeftVal, m_RightVal, dd, len, h, rt, pt, fm, lscalelen);
painter->restore();
painter->save();
// 定义分界线坐标
QPointF lineABottom(8.0f, m_LeftVal);
QPointF lineATop(30.0f, m_RightVal);
QPointF lineBBottom(30.0f, m_LeftVal);
QPointF lineBTop(120.0f, m_RightVal);
QPointF lineCBottom(120.0f, m_LeftVal);
QPointF lineCTop(500.0f, m_RightVal);
painter->setPen(QPen(Qt::black, 2));
// 绘制线A
{
float x1, y1, x2, y2;
// X坐标转换
if(lineABottom.x() <= 0) lineABottom.setX(timemin);
if(m_pViewInfoLogmud->GetTLogarithmic() == AXIS_LOGARITHMIC) {
x1 = rt.left()+dd+(log10(lineABottom.x())-log10(timemin))*len/dtime;
}
// Y坐标转换
if(lineABottom.y() <= 0) lineABottom.setY(m_LeftVal);
if(Logarithmic == AXIS_LOGARITHMIC) {
float val = lineABottom.y();
if(val <= 0) val = 0.1f;
y1 = (log10(val)-lval)/(rval-lval)*h;
}
if(y1 < 0) y1 = 0;
if(y1 > h) y1 = h;
y1 = pt1.y()+h-y1;
// X坐标转换
if(lineATop.x() <= 0) lineATop.setX(timemin);
if(m_pViewInfoLogmud->GetTLogarithmic() == AXIS_LOGARITHMIC) {
x2 = rt.left()+dd+(log10(lineATop.x())-log10(timemin))*len/dtime;
}
// Y坐标转换
if(lineATop.y() <= 0) lineATop.setY(m_LeftVal);
if(Logarithmic == AXIS_LOGARITHMIC) {
float val = lineATop.y();
if(val <= 0) val = 0.1f;
y2 = (log10(val)-lval)/(rval-lval)*h;
}
if(y2 < 0) y2 = 0;
if(y2 > h) y2 = h;
y2 = pt1.y()+h-y2;
painter->drawLine(QPointF(x1, y1), QPointF(x2, y2));
}
// 绘制线B
{
float x1, y1, x2, y2;
// X坐标转换
if(lineBBottom.x() <= 0) lineBBottom.setX(timemin);
if(m_pViewInfoLogmud->GetTLogarithmic() == AXIS_LOGARITHMIC) {
x1 = rt.left()+dd+(log10(lineBBottom.x())-log10(timemin))*len/dtime;
}
// Y坐标转换
if(lineBBottom.y() <= 0) lineBBottom.setY(m_LeftVal);
if(Logarithmic == AXIS_LOGARITHMIC) {
float val = lineBBottom.y();
if(val <= 0) val = 0.1f;
y1 = (log10(val)-lval)/(rval-lval)*h;
}
if(y1 < 0) y1 = 0;
if(y1 > h) y1 = h;
y1 = pt1.y()+h-y1;
// X坐标转换
if(lineBTop.x() <= 0) lineBTop.setX(timemin);
if(m_pViewInfoLogmud->GetTLogarithmic() == AXIS_LOGARITHMIC) {
x2 = rt.left()+dd+(log10(lineBTop.x())-log10(timemin))*len/dtime;
}
// Y坐标转换
if(lineBTop.y() <= 0) lineBTop.setY(m_LeftVal);
if(Logarithmic == AXIS_LOGARITHMIC) {
float val = lineBTop.y();
if(val <= 0) val = 0.1f;
y2 = (log10(val)-lval)/(rval-lval)*h;
}
if(y2 < 0) y2 = 0;
if(y2 > h) y2 = h;
y2 = pt1.y()+h-y2;
painter->drawLine(QPointF(x1, y1), QPointF(x2, y2));
}
// 绘制线C
{
float x1, y1, x2, y2;
// X坐标转换
if(lineCBottom.x() <= 0) lineCBottom.setX(timemin);
if(m_pViewInfoLogmud->GetTLogarithmic() == AXIS_LOGARITHMIC) {
x1 = rt.left()+dd+(log10(lineCBottom.x())-log10(timemin))*len/dtime;
}
// Y坐标转换
if(lineCBottom.y() <= 0) lineCBottom.setY(m_LeftVal);
if(Logarithmic == AXIS_LOGARITHMIC) {
float val = lineCBottom.y();
if(val <= 0) val = 0.1f;
y1 = (log10(val)-lval)/(rval-lval)*h;
}
if(y1 < 0) y1 = 0;
if(y1 > h) y1 = h;
y1 = pt1.y()+h-y1;
// X坐标转换
if(lineCTop.x() <= 0) lineCTop.setX(timemin);
if(m_pViewInfoLogmud->GetTLogarithmic() == AXIS_LOGARITHMIC) {
x2 = rt.left()+dd+(log10(lineCTop.x())-log10(timemin))*len/dtime;
}
// Y坐标转换
if(lineCTop.y() <= 0) lineCTop.setY(m_LeftVal);
if(Logarithmic == AXIS_LOGARITHMIC) {
float val = lineCTop.y();
if(val <= 0) val = 0.1f;
y2 = (log10(val)-lval)/(rval-lval)*h;
}
if(y2 < 0) y2 = 0;
if(y2 > h) y2 = h;
y2 = pt1.y()+h-y2;
painter->drawLine(QPointF(x1, y1), QPointF(x2, y2));
}
// 添加区域标签
painter->setPen(m_pViewInfoLogmud->GetColor());
// 计算标签位置
float labelY = pt1.y() + h*0.3f; // 在高度的1/3处
// 计算各标签X坐标
float labelAX, labelBX, labelCX, labelDX;
// X坐标转换
labelAX = rt.left()+dd+(log10(15.0f)-log10(timemin))*len/dtime - fm.width(labelA)/2;
labelBX = rt.left()+dd+(log10(60.0f)-log10(timemin))*len/dtime - fm.width(labelB)/2;
labelCX = rt.left()+dd+(log10(300.0f)-log10(timemin))*len/dtime - fm.width(labelC)/2;
labelDX = rt.left()+dd+(log10(700.0f)-log10(timemin))*len/dtime - fm.width(labelD)/2;
painter->drawText(QPointF(labelAX-5, labelY), labelA);
painter->drawText(QPointF(labelBX-5, labelY), labelB);
painter->drawText(QPointF(labelCX-5, labelY), labelC);
painter->drawText(QPointF(labelDX-2, labelY), labelD);
// 添加深度值和坐标轴标题
DrawDepthAndAxisLabels(painter, resultitem->depth, dd, w, h, rt, pt, fm, lscalelen,
"C2/C1(X1000)", "C3/C1(X1000)");
// 绘制投点
DrawDataPoint(painter, wh, bh, timemin, timemax,
m_LeftVal, m_RightVal, dd, len, h, rt, pt1, Logarithmic);
// 绘制辅助线
painter->drawLine(QPointF(rt.left(), pt1.y()), QPointF(rt.left()+rt.width()/10, pt1.y()));
// 图例左上角位置
float legendX = rt.left() + dd + 5;
float legendY = pt1.y() + 5;
float lineSpacing = fm.height() + 2;
// 图例文字
QVector<QString> legendItems;
legendItems.append("A: 干气或水层气");
legendItems.append("B: 天然气 → 凝析油");
legendItems.append("C: 伴生气 → 油");
legendItems.append("D: 向氧化油过渡");
for(int i=0; i<legendItems.size(); ++i){
float y = legendY + i*lineSpacing;
painter->drawText(QPointF(legendX, y + fm.ascent()), legendItems[i]);
}
// 绘制完成后恢复原始设置
m_pViewInfoLogmud->SetLogarithmic(originalLogarithmic);
m_pViewInfoLogmud->SetTLogarithmic(originalTLogarithmic);
painter->restore();
}//绘制对数图版右括号
// 如果是交会图版类型
/* else if(resultitem->type==3){
int originalLogarithmic = m_pViewInfoLogmud->GetLogarithmic();
int originalTLogarithmic = m_pViewInfoLogmud->GetTLogarithmic();
// 临时设置为对数坐标系
m_pViewInfoLogmud->SetLogarithmic(AXIS_LINEAR); // 设置Y轴为线性坐标系
m_pViewInfoLogmud->SetTLogarithmic(AXIS_LINEAR); // 设置X轴为线性坐标系
float timemin = 0.0f;
float timemax = 5.0f;
float m_LeftVal = 0.0f;
float m_RightVal = 1.0f;
if (resultitem->WH > timemax) {
// 将最大值扩展到下一个10的幂次方
timemax = pow(10, ceil(log10(resultitem->WH)));
}
// 检查Y轴 (BH值)
if (resultitem->BH > m_RightVal) {
// 将最大值扩展到下一个10的幂次方
m_RightVal = pow(10, ceil(log10(resultitem->BH)));
}
float lval = m_LeftVal;
int Logarithmic = m_pViewInfoLogmud->GetLogarithmic();
float rval = m_RightVal;
if(Logarithmic == AXIS_LOGARITHMIC){
if(rval <= 0) rval = 0.1f;
rval = log10(rval);
}
// 重新计算X轴范围
float dtime = timemax - timemin;
if(m_pViewInfoLogmud->GetTLogarithmic() == AXIS_LOGARITHMIC) {
dtime = log10(timemax) - log10(timemin);
}
if(dtime == 0) dtime = 1;
int fnum=10;// 默认网格数为10
//设置X轴网格数和开始绘制X轴线性网格
if(m_pViewInfoLogmud->GetTLogarithmic()==AXIS_LINEAR) //如果X轴是线性坐标系
{
DrawXAxisLinearGrid(painter, timemin, timemax, dd, len, h, rt, pt, pt1, fm, fnum);
}
//设置Y轴网格数和开始绘制Y轴线性网格
fnum=10;
if(m_pViewInfoLogmud->GetLogarithmic()==AXIS_LOGARITHMIC) // 如果Y轴是对数坐标系
{
DrawYAxisLogarithmicGrid(painter, m_LeftVal, m_RightVal, dd, len, h, rt, pt, fm, lscalelen);
}
else // 如果Y轴是线性坐标系循环绘制fnum+1条网格线
{
DrawYAxisLinearGrid(painter, m_LeftVal, m_RightVal, dd, len, h, rt, pt, fm, lscalelen, fnum);
}
// 绘制深度和轴标题
DrawDepthAndAxisLabels(painter, resultitem->depth, dd, w, h, rt, pt, fm, lscalelen, pCore,"C1/TG","C2/C3");
// 绘制投点
DrawDataPoint(painter, resultitem->WH, resultitem->BH, timemin, timemax,
m_LeftVal, m_RightVal, dd, len, h, rt, pt1, Logarithmic);
// 绘制辅助线
painter->drawLine(QPointF(rt.left(), pt1.y()), QPointF(rt.left()+rt.width()/20, pt1.y()));
// 绘制完成后恢复原始设置
m_pViewInfoLogmud->SetLogarithmic(originalLogarithmic);
m_pViewInfoLogmud->SetTLogarithmic(originalTLogarithmic);
}//判断交会图版的右括号
else if(resultitem->type==4){
painter->save();
// 设置坐标范围
float timemax = 0.17f; // 三角图版的坐标轴逻辑长度
// 从resultitem中获取比例值
float ratioC2 = resultitem->WH; // 左侧
float ratioC3 = resultitem->BH; // 底边
float ratioNC4 = resultitem->DH; // 右侧
// 约束异常比例值,避免内三角计算把图形拉到图道外。
if(ratioC2!=ratioC2||ratioC2<0) ratioC2=0;
if(ratioC3!=ratioC3||ratioC3<0) ratioC3=0;
if(ratioNC4!=ratioNC4||ratioNC4<0) ratioNC4=0;
if(ratioC2>timemax) ratioC2=timemax;
if(ratioC3>timemax) ratioC3=timemax;
if(ratioNC4>timemax) ratioNC4=timemax;
float ratioSum=ratioC2+ratioC3+ratioNC4;
if(ratioSum>timemax*0.98f&&ratioSum>1e-6f)
{
float scaleDown=timemax*0.98f/ratioSum;
ratioC2*=scaleDown;
ratioC3*=scaleDown;
ratioNC4*=scaleDown;
}
float scaleFactor = 1.5f;
// 计算等边三角形的实际尺寸
float availableWidth = len;
float availableHeight = h * 1.2f;
float triangleSide = qMin(availableWidth, availableHeight * 2.0f / sqrt(3.0f)) * scaleFactor;
// 确保缩放后三角形不超出可用空间
if (triangleSide > availableWidth) {
triangleSide = availableWidth;
}
if (triangleSide * sqrt(3.0f) / 2.0f > availableHeight) {
triangleSide = availableHeight * 2.0f / sqrt(3.0f);
}
//坐标设置
float scale = triangleSide / timemax; // 计算缩放比例
float offsetX = rt.left() + dd + (availableWidth - triangleSide) / 2.0f; // 居中显示
float offsetY = pt1.y() + h;
float sin60 = sqrt(3.0f) / 2.0f;
float cos60 = 0.5f;
float tan60 = sqrt(3.0f);
float triangleHeight = timemax * sin60;
// 逻辑坐标转像素坐标
auto GetPoint = [&](float x, float y) -> QPointF {
return QPointF(
offsetX + x * scale,
offsetY - y * scale
);
};
QPointF pointA = GetPoint(0.0f, 0.0f); // 左下角
QPointF pointB = GetPoint(timemax/2.0f, triangleHeight); // 顶部
QPointF pointC = GetPoint(timemax, 0.0f); // 右下角
// 绘制三角形框架
QPen penAxis(Qt::black, 2);
painter->setPen(penAxis);
painter->drawPolygon(QPolygonF() << pointA << pointB << pointC);
// 绘制辅助线网格
QPen penGuide(QColor(220, 220, 220), 1);
painter->setPen(penGuide);
int steps = 17;
float step = timemax / steps;
// 计算网格线点集
QVector<QPointF> pointsBottom;
QVector<QPointF> pointsLeft;
QVector<QPointF> pointsRight;
//绘制辅助线
for (int i = 0; i <= steps; i++) {
float ratio = (float)i / steps;
// 底边上的点 (从A到C)
pointsBottom.append(GetPoint(timemax * ratio, 0.0f));
// 左侧边上的点 (从A到B)
float leftX = timemax * ratio / 2.0f;
float leftY = timemax * ratio * sin60;
pointsLeft.append(GetPoint(leftX, leftY));
// 右侧边上的点 (从C到B)
float rightX = timemax - (timemax * ratio / 2.0f);
float rightY = timemax * ratio * sin60;
pointsRight.append(GetPoint(rightX, rightY));
}
// 绘制网格线
for (int i = 1; i < steps; i++) {
// 绘制三条方向的网格线
painter->drawLine(pointsBottom[i], pointsLeft[i]);
painter->drawLine(pointsLeft[i], pointsRight[i]);
painter->drawLine(pointsBottom[i], pointsRight[steps - i]);
}
painter->restore();
//绘制价值区(气产区和油产区)
painter->save();
QPainterPath outerTriClipPath;
outerTriClipPath.addPolygon(QPolygonF() << pointA << pointB << pointC);
painter->setClipPath(outerTriClipPath,Qt::IntersectClip);
// 气产区(黄色)
QVector<QPointF> gasArea;
gasArea.append(QPointF(0.06445464f, 0.1097643f));
gasArea.append(QPointF(0.07913243f, 0.13444f));
gasArea.append(QPointF(0.08508863f, 0.1333764f));
gasArea.append(QPointF(0.09147028f, 0.1206131f));
gasArea.append(QPointF(0.09402294f, 0.1065735f));
gasArea.append(QPointF(0.08998123f, 0.09338477f));
gasArea.append(QPointF(0.06445464f, 0.1097643f));
// 油产区(橙色)
QVector<QPointF> oilArea;
oilArea.append(QPointF(0.06445464f, 0.1097643f));
oilArea.append(QPointF(0.05870667f, 0.09656f));
oilArea.append(QPointF(0.05666667f, 0.068f));
oilArea.append(QPointF(0.06573334f, 0.05168f));
oilArea.append(QPointF(0.08613333f, 0.0374f));
oilArea.append(QPointF(0.09633333f, 0.04465333f));
oilArea.append(QPointF(0.09814667f, 0.06074667f));
oilArea.append(QPointF(0.09293333f, 0.08658667f));
oilArea.append(QPointF(0.08998123f, 0.09338477f));
oilArea.append(QPointF(0.06445464f, 0.1097643f));
// 转换逻辑坐标到像素坐标
QVector<QPointF> gasPixelPoints;
for (int i = 0; i < gasArea.size(); i++) {
gasPixelPoints.append(GetPoint(gasArea[i].x(), gasArea[i].y()));
}
// 使用平滑曲线绘制气产区
QPainterPath gasPath;
if (gasPixelPoints.size() > 0) {
gasPath.moveTo(gasPixelPoints[0]);
// 创建平滑曲线
for (int i = 1; i < gasPixelPoints.size(); i++) {
QPointF p1 = gasPixelPoints[i-1];
QPointF p2 = gasPixelPoints[i];
QPointF midPoint = (p1 + p2) / 2.0;
gasPath.quadTo(p1, midPoint);
}
// 闭合路径
if (gasPixelPoints.size() > 2) {
QPointF p1 = gasPixelPoints.last();
QPointF p2 = gasPixelPoints.first();
QPointF midPoint = (p1 + p2) / 2.0;
gasPath.quadTo(p1, midPoint);
gasPath.quadTo(p2, gasPixelPoints[0]);
}
}
// 绘制气产区
painter->setBrush(QColor(0xfe, 0xfa, 0xb2, 200)); // 黄色200透明度
painter->setPen(Qt::NoPen);
painter->drawPath(gasPath);
// 转换油产区逻辑坐标到像素坐标
QPainterPath oilPath;
QVector<QPointF> oilPixelPoints;
for (int i = 0; i < oilArea.size(); i++) {
oilPixelPoints.append(GetPoint(oilArea[i].x(), oilArea[i].y()));
}
if (oilPixelPoints.size() > 0) {
oilPath.moveTo(oilPixelPoints[0]);
// 创建平滑曲线
for (int i = 1; i < oilPixelPoints.size(); i++) {
QPointF p1 = oilPixelPoints[i-1];
QPointF p2 = oilPixelPoints[i];
QPointF midPoint = (p1 + p2) / 2.0;
oilPath.quadTo(p1, midPoint);
}
// 闭合路径
if (oilPixelPoints.size() > 2) {
QPointF p1 = oilPixelPoints.last();
QPointF p2 = oilPixelPoints.first();
QPointF midPoint = (p1 + p2) / 2.0;
oilPath.quadTo(p1, midPoint);
oilPath.quadTo(p2, oilPixelPoints[0]);
}
}
// 绘制油产区
painter->setBrush(QColor(0xf7, 0xb7, 0x89, 200)); // 橙色200透明度
painter->drawPath(oilPath);
// 气产区文字
QPointF gasLabelPos = GetPoint(0.067f, 0.11f); // 根据气产区大概位置
painter->setPen(Qt::black);
painter->setFont(QFont("Arial", 10, QFont::Bold));
painter->drawText(gasLabelPos, "气产区");
// 油产区文字
QPointF oilLabelPos = GetPoint(0.064f, 0.07f); // 根据油产区大概位置
painter->setPen(Qt::black);
painter->setFont(QFont("Arial", 10, QFont::Bold));
painter->drawText(oilLabelPos, "油产区");
// 计算内三角顶点
// 顶点A' (C2比例)
float aXp = ratioC2 * cos60 + ratioNC4;
float aYp = ratioC2 * sin60;
// 顶点B' (C3比例)
float bXp = (timemax - ratioC3 - ratioNC4) / 2 + ratioNC4;
float bYp = (bXp - ratioNC4) * tan60;
// 顶点C' (nC4比例)
float cYp = aYp;
float cXp = timemax - cYp / tan60 - ratioC3;
auto ClampToTriangle = [timemax,triangleHeight,tan60](float& x,float& y)
{
if(y<0) y=0;
if(y>triangleHeight) y=triangleHeight;
float minX=y/tan60;
float maxX=timemax-y/tan60;
if(x<minX) x=minX;
if(x>maxX) x=maxX;
};
ClampToTriangle(aXp,aYp);
ClampToTriangle(bXp,bYp);
ClampToTriangle(cXp,cYp);
// 计算价值点M两条直线的交点
float lineAk = qAbs(aXp)>1e-6f ? aYp / aXp : 0.0f; // 从原点(0,0)到A'的斜率
float lineCk = qAbs(cXp-timemax)>1e-6f ? cYp / (cXp - timemax) : 0.0f; // 从底边右顶点到C'的斜率
float lineCb = -lineCk * timemax; // 截距
float mX = qAbs(lineAk-lineCk)>1e-6f ? lineCb / (lineAk - lineCk) : bXp; // 交点X
float mY = mX * lineAk; // 交点Y
ClampToTriangle(mX,mY);
// 转换内三角形顶点到像素坐标
QPointF pointAp = GetPoint(aXp, aYp);
QPointF pointBp = GetPoint(bXp, bYp);
QPointF pointCp = GetPoint(cXp, cYp);
QPointF pointM = GetPoint(mX, mY);
// 绘制内价值三角(红色边框)
QPen penTriangle(QColor(255, 0, 0), 2);
painter->setPen(penTriangle);
painter->setBrush(Qt::NoBrush);
painter->drawPolygon(QPolygonF() << pointAp << pointBp << pointCp);
// 绘制价值点(红色实心圆)
QPen penPoint(QColor(255, 0, 0), 1);
painter->setPen(penPoint);
painter->setBrush(QBrush(QColor(255, 0, 0)));
float pointRadius = 2.0f * (scaleFactor > 1.0f ? scaleFactor * 0.8f : 1.0f);
painter->drawEllipse(pointM, pointRadius, pointRadius);
painter->restore();
// 恢复原始坐标系绘制文字
painter->resetTransform();
painter->save();
// 绘制坐标轴标签
painter->setPen(m_pViewInfoLogmud->GetColor());
QString bottomLabel = "C3/Tg";
QString leftLabel = "C2/Tg";
QString rightLabel = "nC4/Tg";
// 计算标签位置
QFontMetrics fm = painter->fontMetrics();
int textHeight = fm.height();
// 调整标签位置
QPointF leftMid((pointA.x() + pointB.x()) / 2, (pointA.y() + pointB.y()) / 2);
painter->drawText(
QPointF(pointA.x() - fm.width(leftLabel) - 5,
leftMid.y()),
leftLabel);
// 右侧标签
QPointF rightMid((pointC.x() + pointB.x()) / 2, (pointC.y() + pointB.y()) / 2);
painter->drawText(
QPointF(pointC.x() - fm.width(rightLabel) + 15,
rightMid.y() - 15),
rightLabel);
// 绘制坐标刻度
QPen scalePen(Qt::black, 1);
// 在三角形边上绘制刻度 - 调整刻度长度
float tickLength = 3.0f * (scaleFactor > 1.0f ? scaleFactor * 0.8f : 1.0f); // 调整刻度长度
for (int i = 1; i < steps; i++) {
if (i % 5 == 0) {
float ratio = (float)i / steps;
float value = i * 0.01f;
// 底部刻度
QPointF bottomPt(pointA.x() + (pointC.x() - pointA.x()) * ratio, pointA.y());
painter->setPen(scalePen);
painter->drawLine(bottomPt.x(), bottomPt.y(), bottomPt.x(), bottomPt.y() - tickLength);
painter->setPen(m_pViewInfoLogmud->GetColor());
if (i == 5 ||i == 15) {
painter->drawText(
QPointF(bottomPt.x() - 15, bottomPt.y() + 14),
QString::number(value, 'f', 2));
}
else
{
painter->drawText(
QPointF(bottomPt.x() - 10, bottomPt.y() + 14),
QString::number(value, 'f', 1));
}
// 左侧刻度
QPointF leftPt(pointA.x() + (pointB.x() - pointA.x()) * ratio, pointA.y() + (pointB.y() - pointA.y()) * ratio);
painter->setPen(scalePen);
painter->drawLine(leftPt.x(), leftPt.y(), leftPt.x() + tickLength, leftPt.y());
painter->setPen(m_pViewInfoLogmud->GetColor());
// 调整左侧刻度标签位置
painter->drawText(
QPointF(leftPt.x() - fm.width(QString::number(value, 'f', 2)) - 3,
leftPt.y() + fm.height()/4),
QString::number(value, 'f', 2));
// 右侧刻度
QPointF rightPt(pointC.x() + (pointB.x() - pointC.x()) * ratio, pointC.y() + (pointB.y() - pointC.y()) * ratio);
painter->setPen(scalePen);
painter->drawLine(rightPt.x(), rightPt.y(), rightPt.x() - tickLength, rightPt.y());
painter->setPen(m_pViewInfoLogmud->GetColor());
// 调整右侧刻度标签位置
painter->drawText(
QPointF(rightPt.x() + 4,
rightPt.y() + fm.height()/4 + 3),
QString::number(value, 'f', 2));
}
}
// 重新组织底部标签和深度值位置
float baseY = pointA.y() + fm.height() + 12;
// 绘制底部标签
painter->drawText(
QPointF(rt.left() + dd + (w - fm.width(bottomLabel)) / 2,
baseY),
bottomLabel);
// 在底部绘制深度值
QString depthText = toString(resultitem->depth) + "米";
float depthTextWidth = fm.width(depthText);
float depthY = baseY + fm.height() -2;
// 根据视图配置确定深度值位置
if (m_pViewInfoLogmud->GetisBottom() == 0 || m_pViewInfoLogmud->GetisBottom() == 1) {
painter->drawText(
QPointF(rt.left() + dd + (w - depthTextWidth) / 2,
depthY),
depthText);
} else if (m_pViewInfoLogmud->GetisBottom() == 2) {
painter->drawText(
QPointF(rt.left() + rt.width() / 20,
depthY),
depthText);
} else if (m_pViewInfoLogmud->GetisBottom() == 3) {
painter->drawText(
QPointF(rt.right() - depthTextWidth,
depthY),
depthText);
}
painter->restore();
// 与其他图版保持一致:补绘左侧顶部辅助短线。
painter->drawLine(QPointF(rt.left(), pt1.y()), QPointF(rt.left()+rt.width()/10, pt1.y()));
}//判断三角图版的右括号
//绘制星形图版
else if(resultitem->type==5) {
painter->save();
// 定义七个比值名称
QStringList expressionList;
expressionList << "C1/C2" << "C1/C3" << "C2/C3" << "C2/IC4" << "C3/IC4" << "IC4/NC4" << "IC5/NC5";
// 获取七个比值数据
float values[7];
values[0] = resultitem->BH; // ration1 (C1/C2)
values[1] = resultitem->WH; // ration2 (C1/C3)
values[2] = resultitem->DH; // ration3 (C2/C3)
values[3] = resultitem->A; // ration4 (C2/IC4)
values[4] = resultitem->B; // ration5 (C3/IC4)
values[5] = resultitem->C; // ration6 (IC4/NC4)
values[6] = resultitem->D; // ration7 (IC5/NC5)
// 计算最大值并确定坐标轴范围
float maxValue = 0;
for(int i = 0; i < 7; i++) {
if(!(values[i] != values[i]) && values[i] > maxValue)
maxValue = values[i];
}
// 确定坐标轴最大值和网格线数量
float logicLen = 10.0f;
int logicSepNum = 10;
if(maxValue <= 1.0f) {
logicLen = ceil(maxValue * 10) / 10;
logicSepNum = (int)(logicLen * 10);
} else if(maxValue <= 10.0f) {
logicLen = ceil(maxValue / 2) * 2;
logicSepNum = (int)logicLen / 2;
} else if(maxValue <= 50.0f) {
logicLen = ceil(maxValue / 5) * 5;
logicSepNum = (int)logicLen / 5;
} else {
logicLen = ceil(maxValue / 10) * 10;
logicSepNum = 10;
}
if(maxValue == 0) {
maxValue = 10;
logicLen = 10;
logicSepNum = 10;
}
// 计算绘图区域和缩放比例
float scale = h / logicLen / 2;
float offsetX = rt.left() + dd + len/2;
float offsetY = pt1.y() + h/2;
// 绘制中心点
painter->setBrush(QBrush(QColor(211, 211, 211)));
painter->setPen(Qt::NoPen);
painter->drawEllipse(QPointF(offsetX, offsetY), 3, 3);
// 绘制雷达刻度线
int angleNum = expressionList.size();
QPen gridPen(QColor(220, 220, 220), 1);
// 循环绘制刻度线
for(int i = 0; i < logicSepNum; i++) {
painter->save();
float value = logicLen / logicSepNum;
float polarLen = (i + 1) * value;
// 绘制多边形网格
painter->setPen(gridPen);
for(int j = 0; j < angleNum; j++) {
float angle1 = j * 2 * M_PI / angleNum;
float angle2 = ((j + 1) % angleNum) * 2 * M_PI / angleNum;
float x1 = polarLen * sin(angle1) * scale;
float y1 = polarLen * cos(angle1) * scale;
float x2 = polarLen * sin(angle2) * scale;
float y2 = polarLen * cos(angle2) * scale;
painter->drawLine(
QPointF(offsetX + x1, offsetY - y1),
QPointF(offsetX + x2, offsetY - y2)
);
}
// 绘制刻度值
painter->setPen(m_pViewInfoLogmud->GetColor());
QString scaleText = toString(polarLen);
float textWidth = fm.width(scaleText);
painter->drawText(
QPointF(offsetX - textWidth/2, offsetY - polarLen * scale - 5),
scaleText
);
painter->restore();
}
// 绘制坐标轴名称
painter->setPen(m_pViewInfoLogmud->GetColor());
for(int i = 0; i < angleNum; i++) {
float angle = i * 2 * M_PI / angleNum;
float sin_val = sin(angle);
float cos_val = cos(angle);
float x = (logicLen + logicLen * 0.1) * sin_val * scale;
float y = (logicLen + logicLen * 0.1) * cos_val * scale;
QString axisName = expressionList[i];
float textWidth = fm.width(axisName);
float textHeight = fm.height();
// 根据象限调整文字位置
float textX = offsetX + x;
float textY = offsetY - y;
if(sin_val >= 0) {
// 右侧
textX += 2;
} else {
// 左侧
textX -= textWidth + 2;
}
if(cos_val >= 0) {
// 上方
textY -= 2;
} else {
// 下方
textY += textHeight + 2;
}
painter->drawText(QPointF(textX, textY), axisName);
}
// 绘制数据多边形
QPolygonF dataPolygon;
for(int i = 0; i < angleNum; i++) {
float angle = i * 2 * M_PI / angleNum;
float value = values[i];
// 处理无效值
if((value != value) || value < 0) value = 0;
if(value > logicLen) value = logicLen;
float x = value * sin(angle) * scale;
float y = value * cos(angle) * scale;
dataPolygon << QPointF(offsetX + x, offsetY - y);
}
dataPolygon << dataPolygon[0]; // 闭合多边形
// 绘制数据连线
painter->setPen(QPen(Qt::red, 2));
painter->setBrush(QBrush(QColor(255, 0, 0, 50)));
painter->drawPolygon(dataPolygon);
// 在多边形顶点绘制数据点
painter->setBrush(QBrush(Qt::red));
for(int i = 0; i < dataPolygon.size() - 1; i++) {
painter->drawEllipse(dataPolygon[i], 3, 3);
}
// 绘制深度值和标题
DrawDepthAndAxisLabels(painter, resultitem->depth, dd, w, h, rt, pt, fm, lscalelen,
pCore, " ", " ");
painter->restore();
// 绘制辅助线
painter->drawLine(QPointF(rt.left(), pt1.y()), QPointF(rt.left()+rt.width()/20, pt1.y()));
}//星形图版右括号
else if(resultitem->type==6){
painter->save();
// 设置坐标范围
float mgMin = 0.0f;
float mgMax = 13.0f;
float caMin = 21.7f;
float caMax = 40.0f;
float siMin = 0.0f;
float siMax = 28.0f;
float scaleFactor = 1.5f;
// 从resultitem中获取元素含量
float mg = resultitem->WH; // Mg含量
float si = resultitem->BH; // Si含量
float ca = 100.0f - mg - si; // 计算Ca含量
// 计算等边三角形的实际尺寸
float availableWidth = len;
float availableHeight = h * 1.2f;
float triangleSide = qMin(availableWidth, availableHeight * 2.0f / sqrt(3.0f)) * scaleFactor;
if (triangleSide > availableWidth) {
triangleSide = availableWidth;
}
if (triangleSide * sqrt(3.0f) / 2.0f > availableHeight) {
triangleSide = availableHeight * 2.0f / sqrt(3.0f);
}
// 坐标设置
float xLen = mgMax - mgMin;
float scale = len / xLen; // 计算缩放比例
float offsetX = rt.left() + dd + (availableWidth - len) / 2.0f; // 居中显示
float offsetY = pt1.y() + h;
float sin60 = sqrt(3.0f) / 2.0f;
float cos60 = 0.5f;
// 设置边距和坐标轴长度
float picMarginLeft = rt.left() + dd + (availableWidth - triangleSide) / 2.0f;
float picMarginBottom = pt1.y() + h;
float axisXLen = triangleSide;
float axisYLen = triangleSide * sqrt(3.0f) / 2.0f;
// 缩放比例
float scaleX = axisXLen / (mgMax - mgMin);
float scaleY = axisYLen / (siMax - siMin);
auto TranslateMgPos = [&](float mgVal) -> float {
return picMarginLeft + (mgVal - mgMin) * scaleX;
};
auto TranslateCaPos = [&](float caVal) -> float {
return picMarginLeft + ((caVal - caMin) / (caMax - caMin)) * axisXLen;
};
auto TranslateSiPos = [&](float siVal) -> float {
return picMarginBottom - (siVal - siMin) * scaleY;
};
// 计算 形的三个点
QPointF pointA = QPointF(TranslateMgPos(0), TranslateSiPos(0)); // 左下角
QPointF pointB = QPointF(TranslateMgPos(6.5), TranslateSiPos(28)); // 顶部
QPointF pointC = QPointF(TranslateMgPos(13), TranslateSiPos(0)); // 右下角
// 绘制三角形框架
QPen penAxis(Qt::black, 2);
painter->setPen(penAxis);
painter->drawPolygon(QPolygonF() << pointA << pointB << pointC);
// 计算中点
float xMid = 6.5f;
// 辅助函数计算两侧点的水平偏移
auto GetMgDelta = [&](float siVal) -> float {
return (siMax - siVal) * (xMid - mgMin) / (siMax - siMin);
};
// 价值区域定义和绘制
QVector<QPair<QString, QVector<QPointF>>> valueAreaList;
// 添加所有价值区
// 1. 泥岩
QVector<QPointF> mudstone;
mudstone.append(QPointF(xMid - GetMgDelta(25.2f), 25.2f));
mudstone.append(QPointF(xMid - GetMgDelta(28.0f), 28.0f));
mudstone.append(QPointF(xMid + GetMgDelta(25.2f), 25.2f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("泥岩", mudstone));
// 2. 含灰泥岩
QVector<QPointF> calcareous;
calcareous.append(QPointF(xMid - GetMgDelta(21.0f), 21.0f));
calcareous.append(QPointF(xMid - GetMgDelta(25.2f), 25.2f));
calcareous.append(QPointF(xMid, 25.2f));
calcareous.append(QPointF(xMid, 21.0f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("含灰泥岩", calcareous));
// 3. 含云泥岩
QVector<QPointF> dolomitic;
dolomitic.append(QPointF(xMid + GetMgDelta(21.0f), 21.0f));
dolomitic.append(QPointF(xMid + GetMgDelta(25.2f), 25.2f));
dolomitic.append(QPointF(xMid, 25.2f));
dolomitic.append(QPointF(xMid, 21.0f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("含云泥岩", dolomitic));
// 4. 灰质泥岩
QVector<QPointF> calcareous2;
calcareous2.append(QPointF(xMid - GetMgDelta(14.0f), 14.0f));
calcareous2.append(QPointF(xMid - GetMgDelta(21.0f), 21.0f));
calcareous2.append(QPointF(xMid, 21.0f));
calcareous2.append(QPointF(xMid, 14.0f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("灰质泥岩", calcareous2));
// 5. 云质泥岩
QVector<QPointF> dolomitic2;
dolomitic2.append(QPointF(xMid + GetMgDelta(14.0f), 14.0f));
dolomitic2.append(QPointF(xMid + GetMgDelta(21.0f), 21.0f));
dolomitic2.append(QPointF(xMid, 21.0f));
dolomitic2.append(QPointF(xMid, 14.0f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("云质泥岩", dolomitic2));
// 6. 泥灰岩
QVector<QPointF> marlstone;
marlstone.append(QPointF(xMid - GetMgDelta(7.0f), 7.0f));
marlstone.append(QPointF(xMid - GetMgDelta(14.0f), 14.0f));
marlstone.append(QPointF(xMid, 14.0f));
marlstone.append(QPointF(xMid, 7.0f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("泥灰岩", marlstone));
// 7. 泥云岩
QVector<QPointF> marlyDolomite;
marlyDolomite.append(QPointF(xMid + GetMgDelta(7.0f), 7.0f));
marlyDolomite.append(QPointF(xMid + GetMgDelta(14.0f), 14.0f));
marlyDolomite.append(QPointF(xMid, 14.0f));
marlyDolomite.append(QPointF(xMid, 7.0f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("泥云岩", marlyDolomite));
// 8. 含泥灰岩
QVector<QPointF> argillaceousLimestone;
argillaceousLimestone.append(QPointF(xMid - GetMgDelta(2.8f), 2.8f));
argillaceousLimestone.append(QPointF(xMid - GetMgDelta(7.0f), 7.0f));
argillaceousLimestone.append(QPointF(xMid, 7.0f));
argillaceousLimestone.append(QPointF(xMid, 2.8f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("含泥灰岩", argillaceousLimestone));
// 9. 含泥云岩
QVector<QPointF> argillaceousDolomite;
argillaceousDolomite.append(QPointF(xMid + GetMgDelta(2.8f), 2.8f));
argillaceousDolomite.append(QPointF(xMid + GetMgDelta(7.0f), 7.0f));
argillaceousDolomite.append(QPointF(xMid, 7.0f));
argillaceousDolomite.append(QPointF(xMid, 2.8f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("含泥云岩", argillaceousDolomite));
// 10. 灰岩
QVector<QPointF> limestone;
limestone.append(QPointF(0.0f, 0.0f));
limestone.append(QPointF(xMid - GetMgDelta(2.8f), 2.8f));
limestone.append(QPointF(xMid - GetMgDelta(2.8f) + 1.3f * ((28.0f - 2.8f) / 28.0f), 2.8f));
limestone.append(QPointF(1.3f, 0.0f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("灰岩", limestone));
// 11. 云岩
QVector<QPointF> dolomite;
dolomite.append(QPointF(13.0f, 0.0f));
dolomite.append(QPointF(xMid + GetMgDelta(2.8f), 2.8f));
dolomite.append(QPointF(xMid + GetMgDelta(2.8f) - 1.3f * ((28.0f - 2.8f) / 28.0f), 2.8f));
dolomite.append(QPointF(11.7f, 0.0f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("云岩", dolomite));
// 12. 含云灰岩
QVector<QPointF> dolomiteLimestone;
dolomiteLimestone.append(QPointF(1.3f, 0.0f));
dolomiteLimestone.append(QPointF(xMid - GetMgDelta(2.8f) + 1.3f * ((28.0f - 2.8f) / 28.0f), 2.8f));
dolomiteLimestone.append(QPointF(xMid - GetMgDelta(2.8f) + 3.2f * ((28.0f - 2.8f) / 28.0f), 2.8f));
dolomiteLimestone.append(QPointF(3.2f, 0.0f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("含云灰岩", dolomiteLimestone));
// 13. 含灰云岩
QVector<QPointF> calcareousDolomite;
calcareousDolomite.append(QPointF(11.7f, 0.0f));
calcareousDolomite.append(QPointF(xMid + GetMgDelta(2.8f) - 1.3f * ((28.0f - 2.8f) / 28.0f), 2.8f));
calcareousDolomite.append(QPointF(xMid + GetMgDelta(2.8f) - (13.0f - 9.7f) * ((28.0f - 2.8f) / 28.0f), 2.8f));
calcareousDolomite.append(QPointF(9.7f, 0.0f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("含灰云岩", calcareousDolomite));
// 14. 云质灰岩
QVector<QPointF> dolomiticalLimestone;
dolomiticalLimestone.append(QPointF(3.2f, 0.0f));
dolomiticalLimestone.append(QPointF(xMid - GetMgDelta(2.8f) + 3.2f * ((28.0f - 2.8f) / 28.0f), 2.8f));
dolomiticalLimestone.append(QPointF(6.5f, 2.8f));
dolomiticalLimestone.append(QPointF(6.5f, 0.0f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("云质灰岩", dolomiticalLimestone));
// 15. 灰质云岩
QVector<QPointF> calcDolomite;
calcDolomite.append(QPointF(9.7f, 0.0f));
calcDolomite.append(QPointF(xMid + GetMgDelta(2.8f) - (13.0f - 9.7f) * ((28.0f - 2.8f) / 28.0f), 2.8f));
calcDolomite.append(QPointF(6.5f, 2.8f));
calcDolomite.append(QPointF(6.5f, 0.0f));
valueAreaList.append(QPair<QString, QVector<QPointF>>("灰质云岩", calcDolomite));
// 绘制所有价值区域
QVector<QRectF> placedAreaLabelRects;
auto IsAreaLabelOverlap = [&placedAreaLabelRects](const QRectF& rect)->bool
{
for(int idx=0;idx<placedAreaLabelRects.size();idx++)
{
if(placedAreaLabelRects[idx].adjusted(-2,-1,2,1).intersects(rect))
{
return true;
}
}
return false;
};
QFont originFont=painter->font();
QFont areaLabelFont=originFont;
areaLabelFont.setPointSize(qMax(7,originFont.pointSize()-1));
painter->setFont(areaLabelFont);
QFontMetrics areaFm(areaLabelFont);
for (int i = 0; i < valueAreaList.size(); i++) {
QVector<QPointF> pixelPoints;
for (int j = 0; j < valueAreaList[i].second.size(); j++) {
pixelPoints.append(QPointF(
TranslateMgPos(valueAreaList[i].second[j].x()),
TranslateSiPos(valueAreaList[i].second[j].y())
));
}
// 绘制价值区
QColor areaColor;
// 根据区域类型设置不同颜色
switch (i % 5) {
case 0: areaColor = QColor(255, 240, 200, 150); break; // 浅黄色
case 1: areaColor = QColor(200, 240, 255, 150); break; // 浅蓝色
case 2: areaColor = QColor(200, 255, 200, 150); break; // 浅绿色
case 3: areaColor = QColor(255, 200, 200, 150); break; // 浅红色
case 4: areaColor = QColor(240, 200, 255, 150); break; // 浅紫色
}
// 绘制价值区域
painter->setBrush(areaColor);
painter->setPen(Qt::black);
painter->drawPolygon(pixelPoints);
// 绘制价值区名称
float centerX = 0, centerY = 0;
for (int j = 0; j < pixelPoints.size(); j++) {
centerX += pixelPoints[j].x();
centerY += pixelPoints[j].y();
}
centerX /= pixelPoints.size();
centerY /= pixelPoints.size();
QString labelText=valueAreaList[i].first;
float textW=areaFm.width(labelText)+4;
float textH=areaFm.height()+2;
QVector<QPointF> labelOffsets;
labelOffsets.append(QPointF(0,0));
labelOffsets.append(QPointF(0,-textH*0.6f));
labelOffsets.append(QPointF(0,textH*0.6f));
labelOffsets.append(QPointF(-textW*0.2f,0));
labelOffsets.append(QPointF(textW*0.2f,0));
bool isPlaced=false;
for(int offsetIdx=0;offsetIdx<labelOffsets.size();offsetIdx++)
{
QRectF labelRect(
centerX-textW*0.5f+labelOffsets[offsetIdx].x(),
centerY-textH*0.5f+labelOffsets[offsetIdx].y(),
textW,textH);
if(labelRect.left()<rt.left()+dd||labelRect.right()>rt.left()+dd+w||
labelRect.top()<pt1.y()-2||labelRect.bottom()>pt1.y()+h+2)
{
continue;
}
if(IsAreaLabelOverlap(labelRect)) continue;
painter->drawText(labelRect,Qt::AlignCenter,labelText);
placedAreaLabelRects.append(labelRect);
isPlaced=true;
break;
}
if(!isPlaced)
{
// 保底策略:即使挤也要显示,避免出现区域名丢失。
QRectF fallbackRect(centerX-textW*0.5f,centerY-textH*0.5f,textW,textH);
painter->drawText(fallbackRect,Qt::AlignCenter,labelText);
placedAreaLabelRects.append(fallbackRect);
}
}
painter->setFont(originFont);
// 绘制价值点
float pointX = TranslateMgPos(mg);
float pointY = TranslateSiPos(si);
painter->setBrush(QBrush(QColor(255, 0, 0)));
painter->setPen(QPen(Qt::red, 1));
float pointRadius = 3.0f * (scaleFactor > 1.0f ? scaleFactor * 0.8f : 1.0f);
painter->drawEllipse(QPointF(pointX, pointY), pointRadius, pointRadius);
// 绘制刻度值
QPen textPen(Qt::black, 1);
painter->setPen(textPen);
// Mg和Ca刻度
float mgX[] = { 0, 1.3, 3.2, 6.5, 9.7, 11.7, 13.0 };
float caX[] = { 40, 38.2, 35.4, 30.8, 26.3, 23.5, 21.7 };
for (int i = 0; i < 7; i++) {
// mg刻度
QString mgStr = QString::number(mgX[i], 'f', 1);
QFontMetrics fm = painter->fontMetrics();
painter->drawText(
QPointF(TranslateMgPos(mgX[i]) - fm.width(mgStr)/2,
TranslateSiPos(0) + 16),
mgStr);
// ca刻度
QString caStr = QString::number(caX[i], 'f', 1);
painter->drawText(
QPointF(TranslateCaPos(caX[i]) - fm.width(caStr)/2,
TranslateSiPos(0) + 34),
caStr);
}
// Si刻度
float siY[] = { 0, 2.8, 7.0, 14.0, 21.0, 25.2, 28.0 };
for (int i = 0; i < 7; i++) {
QString siStr = QString::number(siY[i], 'f', 1);
QFontMetrics fm = painter->fontMetrics();
// 左侧Si刻度
painter->drawText(
QPointF(TranslateMgPos(xMid - GetMgDelta(siY[i])) - fm.width(siStr) - 5,
TranslateSiPos(siY[i]) + fm.height()/4),
siStr);
// 右侧Si刻度
painter->drawText(
QPointF(TranslateMgPos(xMid + GetMgDelta(siY[i])) + 5,
TranslateSiPos(siY[i]) + fm.height()/4),
siStr);
}
// 坐标轴标签
QFontMetrics fm = painter->fontMetrics();
painter->drawText(
QPointF(TranslateMgPos(0) - 50, TranslateSiPos(0) + 54),
"Ca%");
painter->drawText(
QPointF(TranslateMgPos(13) + 20, TranslateSiPos(0) + 54),
"Mg%");
painter->drawText(
QPointF(TranslateMgPos(6.5) - 15, TranslateSiPos(28) - 16),
"Si%");
// 绘制深度信息和标题
QString depthText = toString(resultitem->depth) + "米";
QString resultText = "碳酸盐三角图版";
int textWidth = fm.width(depthText);
painter->drawText(
QPointF(rt.left() + dd + (w - textWidth) / 2,
offsetY + 70),
depthText);
painter->drawText(
QPointF(rt.left() + dd + (w - fm.width(resultText)) / 2,
offsetY + 86),
resultText);
painter->restore();
// 与其他图版保持一致:补绘左侧顶部辅助短线。
painter->drawLine(QPointF(rt.left(), pt1.y()), QPointF(rt.left()+rt.width()/10, pt1.y()));
}
//TAS图版
else if(resultitem -> type == 7)
{
//定义颜色和阈值
QColor _valueAreaColors[] = {
// 近似 “玄武岩” 区域颜色(浅绿一类)
// 补充 “碱玄/碧玄岩” 区域(假设浅黄绿
QColor(180, 230, 120),
// 补充 “响岩质碱玄岩” 区域(假设浅灰绿
QColor(150, 200, 150),
// 补充 “粗面玄武岩” 区域(假设浅棕黄
QColor(240, 200, 120),
// 补充 “玄武粗安岩” 区域(假设浅青
QColor(120, 200, 220),
// 补充 “玄武安山岩” 区域(假设浅粉黄
QColor(250, 200, 180),
QColor(149, 239, 149),
// 近似 “粗面/粗面英安岩” 区域颜色(浅蓝一类)
QColor(107, 154, 238),
// 近似 “响岩” 区域颜色(深绿一类,比如图中黄绿色区域可微调
QColor(45, 144, 45),
// 近似 “英安岩、流纹岩” 等粉色系区域(图中粉色调
QColor(253, 144, 10),
// 近似 “安山岩” 等浅粉、浅红区域(调整后更贴近
QColor(208, 99, 99),
// 补充 “副长岩” 区域(假设图中粉色偏深部分
QColor(239, 100, 100),
};
float yLabelMin = 0;
float yLabelMax = 16;
float xLabelMin = 35;
float xLabelMax = 79;
int fnum;// 默认网格数
int xTicks = 44; // 刻度数 = 网格数
int yTicks = 16;
// 设置画笔
// 设置画笔(加粗轴线)
QPen axisPen(Qt::black);
axisPen.setWidth(2);
painter->setPen(axisPen);
QFontMetrics fm = painter -> fontMetrics();
// ==== 坐标框区域 ====
int x0 = rt.left() + dd;
int x1 = rt.left() + dd + len;
int y0 = pt1.y();
int y1 = pt1.y() + h;
// ==== 绘制四边形坐标轴边框 ====
painter->drawLine(x0, y0, x1, y0); // 顶部横线
painter->drawLine(x0, y1, x1, y1); // 底部横线
painter->drawLine(x0, y0, x0, y1); // 左侧竖线
painter->drawLine(x1, y0, x1, y1); // 右侧竖线
// ==== 设置细画笔绘制刻度 ====
QPen tickPen(Qt::black);
tickPen.setWidth(1);
painter->setPen(tickPen);
// ==== 中心X轴画X轴刻度和文字 ====
int yAxisPos = y1; // 中间横轴在底部
for (int i = 0; i <= xTicks; ++i) {
float val = xLabelMin + (xLabelMax - xLabelMin) * i / xTicks;
int x = x0 + i * len / xTicks;
// 小刻度
if (static_cast<int>(val) % 5 != 0) {
painter->drawLine(x, yAxisPos, x, yAxisPos + 5);
}
// 每 5 单位画一次文字
if (static_cast<int>(val) % 5 == 0) {
painter->drawLine(x, yAxisPos, x, yAxisPos + 10);
QString label = QString::number(val, 'f', 0);
painter->drawText(x - fm.width(label) / 2, yAxisPos + 30, label);
}
}
//绘制其他X轴标识符号
// X轴额外信息
QString labels[] = { "超基性", "基性", "中性", "酸性" };
int xThresh[] = { 35, 45, 52, 62, 79 };
// 画 5 条竖线
int xLinePos[5];
xLinePos[0] = x0;
xLinePos[1] = x0 + 10 * len / xTicks;
xLinePos[2] = x0 + 17 * len / xTicks;
xLinePos[3] = x0 + 27 * len / xTicks;
xLinePos[4] = x0 + 44 * len / xTicks;
for (int i = 0; i < 5; ++i) {
painter->drawLine(xLinePos[i], y1 + 35, xLinePos[i], y1 + 60);
}
// 在每两个线之间写文字
for (int i = 0; i < 4; ++i) {
int xCenter = (xLinePos[i] + xLinePos[i + 1]) / 2;
QString label = labels[i];
int textWidth = fm.width(label); // 若 Qt >= 5.11 可改为 horizontalAdvance(label)
painter->drawText(xCenter - textWidth / 2, y1 + 48, label);
}
// ==== 中心Y轴画Y轴刻度和文字 ====
int xAxisPos = x0; // 中间纵轴在左侧
for (int i = 0; i <= yTicks; ++i) {
float val = yLabelMin + (yLabelMax - yLabelMin) * i / yTicks;
int y = y1 - i * h / yTicks;
// 小刻度
if (static_cast<int>(val) % 2 != 0) {
painter->drawLine(xAxisPos - 5, y, xAxisPos, y);
}
// 每 2 单位画一次文字
if (static_cast<int>(val) % 2 == 0) {
painter->drawLine(xAxisPos - 10, y, xAxisPos, y);
QString label = QString::number(val, 'f', 0);
painter->drawText(xAxisPos - 20 - fm.width(label), y + 5, label);
}
}
// ==== 绘制深度值和横纵坐标标题) ====
QString depthText = QString::number(resultitem->depth, 'f', 1) + "米";
int offsetY = 80; // 向下偏移像素数
// --- 绘制深度值 ---
int depthX = x0 + (x1 - x0 - fm.width(depthText)) / 2;
int depthY = y1 + offsetY;
painter->drawText(depthX, depthY, depthText);
// --- 绘制横坐标标题X轴 ---
QString xTitle = "(SiO2(wt.%))";
int xTitleX = x0 + (x1 - x0 - fm.width(xTitle)) / 2;
int xTitleY = depthY + fm.height() + 4;
painter->drawText(xTitleX, xTitleY, xTitle);
// --- 绘制纵坐标标题Y轴 ---
QString yTitle = "Na2O+K2O(wt.%)";
QTransform oldTransform = painter->worldTransform();
int yCenter = y0 + (y1 - y0) / 2;
int yTitleX = x0 - 45; // 可微调位置
int yTitleY = yCenter + fm.width(yTitle) / 2;
// 旋转 -90 度写竖排标题
QTransform transform;
transform.translate(yTitleX, yTitleY);
transform.rotate(-90);
transform.translate(-yTitleX, -yTitleY);
painter->setWorldTransform(transform);
painter->drawText(QPointF(yTitleX, yTitleY), yTitle);
// 恢复变换
painter->setWorldTransform(oldTransform);
//绘制价值区
// 坐标转换函数:将实际坐标点转换为屏幕像素点
QString stoneLabels[] = { "副长岩", "苦橄玄武岩","碱玄/碧玄岩", "响岩质碱玄岩", "碱玄质响岩", "响岩", "玄武岩", "粗面玄武岩", "玄武粗安岩", "玄武安山岩", "粗安岩", "安山岩", "粗面/粗面英安岩", "英安岩", "流纹岩" };
// 构造区域点集
QPolygonF areaPolygon[15];
// 副长岩
areaPolygon[0].append(QPointF(41.0, 0.0));
areaPolygon[0].append(QPointF(41.0, 7.0));
areaPolygon[0].append(QPointF(45.0, 9.4));
areaPolygon[0].append(QPointF(48.4, 11.5));
areaPolygon[0].append(QPointF(52.5, 14.0));
areaPolygon[0].append(QPointF(48.0, 16.0));
areaPolygon[0].append(QPointF(35.0, 16.0));
areaPolygon[0].append(QPointF(35.0, 0.0));
// 苦橄玄武岩
areaPolygon[1].append(QPointF(41, 0.0));
areaPolygon[1].append(QPointF(45, 0.0));
areaPolygon[1].append(QPointF(45, 3));
areaPolygon[1].append(QPointF(41, 3));
// 碱玄/碧玄岩
areaPolygon[2].append(QPointF(41, 3));
areaPolygon[2].append(QPointF(45, 3));
areaPolygon[2].append(QPointF(45, 5));
areaPolygon[2].append(QPointF(49.4, 7.3));
areaPolygon[2].append(QPointF(45, 9.4));
areaPolygon[2].append(QPointF(41, 7));
// 响岩质碱玄岩
areaPolygon[3].append(QPointF(49.4, 7.3));
areaPolygon[3].append(QPointF(53, 9.3));
areaPolygon[3].append(QPointF(48.4, 11.5));
areaPolygon[3].append(QPointF(45, 9.4));
// 碱玄质响岩
areaPolygon[4].append(QPointF(53, 9.3));
areaPolygon[4].append(QPointF(57.6, 11.7));
areaPolygon[4].append(QPointF(52.5, 14));
areaPolygon[4].append(QPointF(48.4, 11.5));
// 响岩
areaPolygon[5].append(QPointF(57.6, 11.7));
areaPolygon[5].append(QPointF(65.7, 16));
areaPolygon[5].append(QPointF(48, 16));
areaPolygon[5].append(QPointF(52.5, 14));
// 玄武岩
areaPolygon[6].append(QPointF(45, 0.0));
areaPolygon[6].append(QPointF(52, 0.0));
areaPolygon[6].append(QPointF(52, 5));
areaPolygon[6].append(QPointF(45, 5));
// 粗面玄武岩
areaPolygon[7].append(QPointF(45, 5));
areaPolygon[7].append(QPointF(52, 5));
areaPolygon[7].append(QPointF(49.4, 7.3));
// 玄武粗安岩
areaPolygon[8].append(QPointF(52, 5));
areaPolygon[8].append(QPointF(57, 5.9));
areaPolygon[8].append(QPointF(53, 9.3));
areaPolygon[8].append(QPointF(49.4, 7.3));
// 玄武安山岩
areaPolygon[9].append(QPointF(52, 0.0));
areaPolygon[9].append(QPointF(57, 0.0));
areaPolygon[9].append(QPointF(57, 5.9));
areaPolygon[9].append(QPointF(52, 5));
// 粗安岩
areaPolygon[10].append(QPointF(57, 5.9));
areaPolygon[10].append(QPointF(63, 7));
areaPolygon[10].append(QPointF(57.6, 11.7));
areaPolygon[10].append(QPointF(53, 9.3));
// 安山岩
areaPolygon[11].append(QPointF(57, 0.0));
areaPolygon[11].append(QPointF(63, 0.0));
areaPolygon[11].append(QPointF(63, 7));
areaPolygon[11].append(QPointF(57, 5.9));
// 粗面/粗面英安岩
areaPolygon[12].append(QPointF(63, 7));
areaPolygon[12].append(QPointF(69, 8));
areaPolygon[12].append(QPointF(69, 16));
areaPolygon[12].append(QPointF(65.7, 16));
areaPolygon[12].append(QPointF(57.6, 11.7));
// 英安岩
areaPolygon[13].append(QPointF(63, 0.0));
areaPolygon[13].append(QPointF(77, 0.0));
areaPolygon[13].append(QPointF(69, 8));
areaPolygon[13].append(QPointF(63, 7));
// 流纹岩
areaPolygon[14].append(QPointF(77, 0.0));
areaPolygon[14].append(QPointF(79, 0.0));
areaPolygon[14].append(QPointF(79, 16));
areaPolygon[14].append(QPointF(69, 16));
areaPolygon[14].append(QPointF(69, 8));
for(int tem = 0; tem < 15; tem++)
{
//构建路径并进行坐标转换(直接转换逻辑坐标为屏幕坐标)
QPainterPath path;
if (!areaPolygon[tem].isEmpty()) {
QPointF pt0 = areaPolygon[tem][0];
float x0Pix = x0 + (pt0.x() - 35) * len / xTicks;
float y0Pix = y1 - pt0.y() * h / yTicks;
path.moveTo(QPointF(x0Pix, y0Pix));
for (int i = 1; i < areaPolygon[tem].size(); ++i) {
QPointF pt = areaPolygon[tem][i];
float xPix = x0 + (pt.x() - 35) * len / xTicks;
float yPix = y1 - pt.y() * h / yTicks;
path.lineTo(QPointF(xPix, yPix));
}
path.closeSubpath(); // 闭合路径
}
//区域填充
painter -> setPen(QPen(Qt::black, 2)); // 粗边框线
painter -> setBrush(_valueAreaColors[tem % 11]); // 你给的颜色
// 获取当前字体并设置更小的字体大小
painter -> drawPath(path);
}
//最后绘制文字
// 绘制居中文本
// 保存画笔状态
painter->save();
// 设置字体并减小字体大小
QFont font = painter->font();
int newPointSize = qMax(6, font.pointSize() - 4); // 确保字体大小不小于6点
font.setPointSize(newPointSize);
painter->setFont(font);
// x 和 y 坐标
double xValues[] = {40, 43, 43, 48, 53, 57, 48.5, 48.5, 53, 54.5, 57.5, 60, 64, 68.5, 75};
double yValues[] = {10, 2, 6, 9, 11, 14, 2.5, 5.5, 6.8, 2.5, 8, 2.5, 11, 2.5, 9};
int labelCount = sizeof(stoneLabels) / sizeof(stoneLabels[0]);
for (int i = 0; i < labelCount; ++i) {
int textWidth = fm.width(stoneLabels[i]);
int textHeight = fm.height();
int x = x0 + (xValues[i] - 35) * len / xTicks - textWidth / 2;
int y = y1 - yValues[i] * h / yTicks - textHeight / 2;
QRect rect(x, y, textWidth, textHeight);
painter->drawText(rect, Qt::AlignCenter, stoneLabels[i]);
}
// 绘制投点
// 设置投点样式
QPen pointPen;
pointPen.setColor(Qt::red);
pointPen.setWidth(2);
painter->setPen(pointPen);
painter->setBrush(Qt::red);
// 绘制投点(圆形)
float pointSize = 3.0f;
painter->drawEllipse(QPointF(x0 + (resultitem->LABEL_X - 35) * len / xTicks, y1 - resultitem->LABEL_Y * h / yTicks), pointSize, pointSize);
painter -> restore();
// 绘制辅助线
painter->drawLine(QPointF(rt.left(), pt1.y()), QPointF(rt.left()+rt.width()/20, pt1.y()));
}
//绘制比值图版
else if(resultitem -> type == 8)
{
// ==== 坐标框区域 ====
int x0 = rt.left() + dd;
int x1 = rt.left() + dd + len;
int y0 = pt1.y();
int y1 = pt1.y() + h;
// 保存原始坐标系设置
int originalLogarithmic = m_pViewInfoLogmud->GetLogarithmic();
int originalTLogarithmic = m_pViewInfoLogmud->GetTLogarithmic();
m_pViewInfoLogmud->SetLogarithmic(AXIS_LOGARITHMIC); // 设置Y轴为对数坐标系
//绘制比值图版
//先建一个样子,横轴实际坐标为比值
float yLabelMin = 1.0f;
float yLabelMax = 1000.0f;
float lval = yLabelMin;
int Logarithmic = m_pViewInfoLogmud->GetLogarithmic();
if(Logarithmic == AXIS_LOGARITHMIC){
if(lval <= 0) lval = 1.0f;
lval = log10(lval);
}
float rval = yLabelMax;
if(Logarithmic == AXIS_LOGARITHMIC){
if(rval <= 0) rval = 1.0f;
rval = log10(rval);
}
// 定义横坐标标签
QString xLabels[] = { "C1/C2", "C1/C3", "C1/(IC4 + NC4)", "C1/(IC5 + NC5)" };
// 先绘制坐标系
int fnum=3;//横轴固定三网格
for (int i = 0; i < 4; ++i) {
// 计算每条竖线的 x 坐标(等间距)
double x = x0 + i * (x1 - x0) / fnum;
painter->save();
// 设置浅灰色画笔
QPen grayPen(Qt::gray, 1);
painter->setPen(grayPen);
// 画竖线
painter->drawLine(QPointF(x, y0), QPointF(x, y1));
int textWidth = fm.width(xLabels[i]);
int textHeight = fm.height();
painter->restore();
// 画文字
QPen blackPen(Qt::black, 1);
painter->setPen(blackPen);
QRect rect(x - textWidth / 2, y1 + 15, textWidth, textHeight);
painter->drawText(rect, Qt::AlignCenter, xLabels[i]);
}
//设置Y轴网格数和开始绘制Y轴对数网格
fnum=3;
fnum=m_pViewInfoLogmud->GetyGrid();
float d1;
float lsc = yLabelMin, rsc = yLabelMax;
float ddd = lsc;
float mm = lsc / ddd;
float x;
float logBase = log10(rsc / lsc);
for (d1 = lsc; d1 <= rsc; d1 = ((int)(d1 / mm + 1.5f)) * mm) {
// 计算当前刻度在画布中的 y 坐标
x = log10(d1 / lsc) / logBase * h;
float yPos = pt.y() + h - x;
bool isMajorTick = fmod(log10(d1), 1.0f) == 0.0f;
if (isMajorTick) {
// 保存画笔状态
painter->save();
// 设置灰色画笔画主刻度线
QPen grayPen(Qt::lightGray, 1);
painter->setPen(grayPen);
painter->drawLine(rt.left() + dd, yPos, rt.left() + dd + len, yPos);
// 设置黑色画笔画刻度标签
QString cs = QString::number(d1, 'g', 4); // 格式化成紧凑浮点数
QRectF tempRect = fm.boundingRect(cs);
QRectF textRect;
textRect.setX(rt.left());
textRect.setY(yPos - tempRect.height() / 2.0f);
textRect.setWidth(dd - fm.width("0") / 2);
textRect.setHeight(tempRect.height());
painter->setPen(Qt::black);
painter->drawText(textRect, Qt::AlignRight | Qt::AlignVCenter, cs);
painter->restore();
} else {
// 次刻度线(浅灰色)
painter->save();
painter->setPen(QPen(Qt::lightGray, 1));
painter->drawLine(rt.left() + dd, yPos, rt.left() + dd + len, yPos);
painter->restore();
}
// 更新刻度递增参数
ddd = d1;
if (ddd < 1.0f) {
while (ddd < 1.0f) ddd *= 10.0f;
} else {
while (ddd > 1.0f) ddd /= 10.0f;
if (ddd < 1.0f) ddd *= 10.0f;
}
mm = d1 / ddd;
}
// 画上下边框线(灰色)
painter->setPen(QPen(Qt::lightGray, 1));
painter->drawLine(rt.left() + dd, pt.y(), rt.left() + dd + len, pt.y());
painter->drawLine(rt.left() + dd, pt.y() + h, rt.left() + dd + len, pt.y() + h);
//从这里结束坐标轴绘制
//绘制折线分界线
// 分界数据
double DataOfLines[3][4] = {
{ 2, 2, 2, 2 },
{ 10, 25, 35, 80 },
{ 90, 500, 800, 1000 }
};
// 创建虚线笔
QPen dashedPen(Qt::black); // 设置颜色为黑色
dashedPen.setWidth(2); // 设置线宽
dashedPen.setStyle(Qt::CustomDashLine); // 使用自定义虚线样式
dashedPen.setDashPattern(QVector<qreal>() << 6.0 << 6.0); // 虚线段长12间隔6
painter->save();
painter->setPen(dashedPen);
// 绘制三条折线
for (int row = 0; row < 3; ++row)
{
QPointF pts[4]; // 每条折线 4 个点
for (int col = 0; col < 4; ++col)
{
double logicX = static_cast<double>(col); // 逻辑 X: 0 ~ 3
double logicY = DataOfLines[row][col]; // 逻辑 Y: 实际数据
// ---------- X轴线性 ----------
float screenX = static_cast<float>(x0 + logicX * (x1 - x0) / 3.0); // 横轴分三格
// ---------- Y轴对数 ----------
float screenY;
float logBase = log10(yLabelMax / yLabelMin);
if (logicY <= 0.0) {
screenY = pt.y() + h; // 小于等于0 → 画在底部
} else {
float logRatio = log10(logicY / yLabelMin) / logBase;
screenY = pt.y() + h * (1.0f - logRatio); // 上大下小
}
pts[col] = QPointF(screenX, screenY);
}
// 用 Qt 的 drawPolyline 绘制线段
painter->drawPolyline(pts, 4);
}
painter->restore();
//绘制其他标识文字
QPen blackPen(Qt::black, 1);
painter->setPen(blackPen);
QString areaLabel[] = {"非产能", "油区", "气区", "非产能"};
double yLabel[4] = {1.7, 8, 190, 950};
for(int i = 0; i < 4; i++)
{
float screenX = static_cast<float>(x0 + 1.5 * (x1 - x0) / 3.0);
float screenY;
float logBase = log10(yLabelMax / yLabelMin);
if (yLabel[i] <= 0.0) {
screenY = pt.y() + h; // 小于等于0 → 画在底部
} else {
float logRatio = log10(yLabel[i] / yLabelMin) / logBase;
screenY = pt.y() + h * (1.0f - logRatio); // 上大下小
}
int textWidth = fm.width(areaLabel[i]);
int textHeight = fm.height();
// 设置字体并减小字体大小
painter -> save();
QFont font = painter->font();
int newPointSize = qMax(6, font.pointSize() - 2); // 确保字体大小不小于6点
font.setPointSize(newPointSize);
painter->setFont(font);
QRect rect(screenX - textWidth / 2, screenY, textWidth, textHeight);
painter->drawText(rect, Qt::AlignCenter, areaLabel[i]);
painter ->restore();
}
//投点
QPointF pts[4]; // 每条折线 4 个点
for (int col = 0; col < 4; ++col)
{
double logicX = static_cast<double>(col); // 逻辑 X: 0 ~ 3
double logicY = resultitem->RATION_Y[col]; // 逻辑 Y: 实际数据
// ---------- X轴线性 ----------
float screenX = static_cast<float>(x0 + logicX * (x1 - x0) / 3.0); // 横轴分三格
// ---------- Y轴对数 ----------
float screenY;
float logBase = log10(yLabelMax / yLabelMin);
if (logicY <= 0.0) {
screenY = pt.y() + h; // 小于等于0 → 画在底部
} else {
float logRatio = log10(logicY / yLabelMin) / logBase;
screenY = pt.y() + h * (1.0f - logRatio); // 上大下小
}
pts[col] = QPointF(screenX, screenY);
}
painter->setPen(QPen(Qt::blue, 2.5));
// 用 Qt 的 drawPolyline 绘制线段
painter->drawPolyline(pts, 4);
//绘制其他包含深度标签和辅助列
// ==== 绘制深度值和横纵坐标标题 ====
painter -> save();
painter->setPen(Qt::black);
QString depthText = QString::number(resultitem->depth, 'f', 1) + "米";
int offsetY = 40; // 向下偏移像素数
// --- 绘制深度值 ---
int depthX = x0 + (x1 - x0 - fm.width(depthText)) / 2;
int depthY = y1 + offsetY;
painter->drawText(depthX, depthY, depthText);
// --- 绘制横坐标标题X轴 ---
QString xTitle = "油区";
int xTitleX = x0 + (x1 - x0 - fm.width(xTitle)) / 2;
int xTitleY = depthY + fm.height() + 4;
painter->drawText(xTitleX, xTitleY, xTitle);
//绘制辅助线
painter->drawLine(QPointF(rt.left(), pt1.y()), QPointF(rt.left()+rt.width()/20, pt1.y()));
painter -> restore();
}
// 湿度比-烃斜率图版
else if(resultitem->type == 9)
{
// 保存原始坐标系设置
int originalLogarithmic = m_pViewInfoLogmud->GetLogarithmic();
int originalTLogarithmic = m_pViewInfoLogmud->GetTLogarithmic();
// 临时设置为线性坐标系
m_pViewInfoLogmud->SetLogarithmic(AXIS_LINEAR); // 设置Y轴为线性坐标系
m_pViewInfoLogmud->SetTLogarithmic(AXIS_LINEAR); // 设置X轴为线性坐标系
// 初始坐标轴范围与C#一致0-1
float timemin = 0.0f;
float timemax = 1.0f;
float m_LeftVal = 0.0f;
float m_RightVal = 1.0f; // 保持为1
if (resultitem->WH > timemax) {
// 将最大值扩展到整数
timemax = ceil(resultitem->WH);
}
// 检查Y轴 (BH值)
if (resultitem->BH > m_RightVal) {
// 将最大值扩展到10的倍数
m_RightVal = ceil(resultitem->BH/10)*10;
}
float lval = m_LeftVal;
int Logarithmic = m_pViewInfoLogmud->GetLogarithmic();
float rval = m_RightVal;
if(Logarithmic == AXIS_LOGARITHMIC){
if(rval <= 0) rval = 0.1f;
rval = log10(rval);
}
// 重新计算X轴范围
float dtime = timemax - timemin;
if(m_pViewInfoLogmud->GetTLogarithmic() == AXIS_LOGARITHMIC) {
dtime = log10(timemax) - log10(timemin);
}
if(dtime == 0) dtime = 1;
int fnum=10;// 默认网格数为10
//设置X轴网格数和开始绘制X轴线性网格
if(m_pViewInfoLogmud->GetTLogarithmic()==AXIS_LINEAR) //如果X轴是线性坐标系
{
DrawXAxisLinearGrid(painter, timemin, timemax, dd, len, h, rt, pt, pt1, fm, fnum);
}
//设置Y轴网格数和开始绘制Y轴线性网格
fnum=10;
if(m_pViewInfoLogmud->GetLogarithmic()==AXIS_LOGARITHMIC) // 如果Y轴是对数坐标系
{
DrawYAxisLogarithmicGrid(painter, m_LeftVal, m_RightVal, dd, len, h, rt, pt, fm, lscalelen);
}
else // 如果Y轴是线性坐标系循环绘制fnum+1条网格线
{
DrawYAxisLinearGrid(painter, m_LeftVal, m_RightVal, dd, len, h, rt, pt, fm, lscalelen, fnum);
}
// 绘制深度和轴标题
DrawDepthAndAxisLabels(painter, resultitem->depth, dd, w, h, rt, pt, fm, lscalelen, pCore,
"湿度比Wh(%)", "烃斜率Gh(C2/C3)");
// 绘制投点
DrawDataPoint(painter, resultitem->WH, resultitem->BH, timemin, timemax,
m_LeftVal, m_RightVal, dd, len, h, rt, pt1, Logarithmic);
// 绘制辅助线
painter->drawLine(QPointF(rt.left(), pt1.y()), QPointF(rt.left()+rt.width()/20, pt1.y()));
// 恢复原始坐标系设置
m_pViewInfoLogmud->SetLogarithmic(originalLogarithmic);
m_pViewInfoLogmud->SetTLogarithmic(originalTLogarithmic);
}//判断湿度比-烃斜率的右括号
// 平衡比-特征比图版
else if(resultitem->type == 10){
// 保存原始坐标系设置
int originalLogarithmic = m_pViewInfoLogmud->GetLogarithmic();
int originalTLogarithmic = m_pViewInfoLogmud->GetTLogarithmic();
// 临时设置为线性坐标系
m_pViewInfoLogmud->SetLogarithmic(AXIS_LINEAR);
m_pViewInfoLogmud->SetTLogarithmic(AXIS_LINEAR);
// 初始坐标轴范围
float timemin = 0.0f;
float timemax = 1.0f;
float m_LeftVal = 0.0f;
float m_RightVal = 1.0f;
// 检查X轴 (平衡比值)
if (resultitem->WH > timemax) {
timemax = ceil(resultitem->WH);
}
// 检查Y轴 (特征比值)
if (resultitem->BH > m_RightVal) {
m_RightVal = ceil(resultitem->BH/10)*10;
}
float lval = m_LeftVal;
int Logarithmic = m_pViewInfoLogmud->GetLogarithmic();
float rval = m_RightVal;
if(Logarithmic == AXIS_LOGARITHMIC){
if(rval <= 0) rval = 0.1f;
rval = log10(rval);
}
// 重新计算X轴范围
float dtime = timemax - timemin;
if(m_pViewInfoLogmud->GetTLogarithmic() == AXIS_LOGARITHMIC) {
dtime = log10(timemax) - log10(timemin);
}
if(dtime == 0) dtime = 1;
int fnum=10;// 默认网格数为10
//设置X轴网格数和开始绘制X轴线性网格
if(m_pViewInfoLogmud->GetTLogarithmic()==AXIS_LINEAR) //如果X轴是线性坐标系
{
DrawXAxisLinearGrid(painter, timemin, timemax, dd, len, h, rt, pt, pt1, fm, fnum);
}
//设置Y轴网格数和开始绘制Y轴线性网格
if(m_pViewInfoLogmud->GetLogarithmic()==AXIS_LOGARITHMIC) // 如果Y轴是对数坐标系
{
DrawYAxisLogarithmicGrid(painter, m_LeftVal, m_RightVal, dd, len, h, rt, pt, fm, lscalelen);
}
else // 如果Y轴是线性坐标系循环绘制fnum+1条网格线
{
DrawYAxisLinearGrid(painter, m_LeftVal, m_RightVal, dd, len, h, rt, pt, fm, lscalelen, fnum);
}
// 绘制深度和轴标题
DrawDepthAndAxisLabels(painter, resultitem->depth, dd, w, h, rt, pt, fm, lscalelen, pCore,
"平衡比Bh", "特征比Ch");
// 绘制投点
DrawDataPoint(painter, resultitem->WH, resultitem->BH, timemin, timemax,
m_LeftVal, m_RightVal, dd, len, h, rt, pt1, Logarithmic);
// 绘制辅助线
painter->drawLine(QPointF(rt.left(), pt1.y()), QPointF(rt.left()+rt.width()/20, pt1.y()));
// 恢复原始坐标系设置
m_pViewInfoLogmud->SetLogarithmic(originalLogarithmic);
m_pViewInfoLogmud->SetTLogarithmic(originalTLogarithmic);
painter->restore();
} //判断平衡比-特征比的右括号
// 火成岩-沉积岩图版
else if(resultitem->type == 11)
{
// 保存原始坐标系设置
int originalLogarithmic = m_pViewInfoLogmud->GetLogarithmic();
int originalTLogarithmic = m_pViewInfoLogmud->GetTLogarithmic();
// 临时设置为线性坐标系
m_pViewInfoLogmud->SetLogarithmic(AXIS_LINEAR);
m_pViewInfoLogmud->SetTLogarithmic(AXIS_LINEAR);
// 初始坐标轴范围与C#一致)
float timemin = 0.0f;
float timemax = 35.0f; // X轴最大值35
float m_LeftVal = 0.0f;
float m_RightVal = 12.0f; // Y轴最大值12
float lval = m_LeftVal;
int Logarithmic = m_pViewInfoLogmud->GetLogarithmic();
float rval = m_RightVal;
// 重新计算X轴范围
float dtime = timemax - timemin;
if(dtime == 0) dtime = 1;
// 保存原始网格数
int originalXGrid = m_pViewInfoLogmud->GetxGrid();
int originalYGrid = m_pViewInfoLogmud->GetyGrid();
// 设置网格数
// X轴0, 5, 10, 15, 20, 25, 30, 35 (间隔5共7个间隔)
m_pViewInfoLogmud->SetxGrid(7);
// Y轴0, 2, 4, 6, 8, 10, 12 (间隔2共6个间隔)
m_pViewInfoLogmud->SetyGrid(6);
// 绘制网格
DrawXAxisLinearGrid(painter, timemin, timemax, dd, len, h, rt, pt, pt1, fm, 7);
DrawYAxisLinearGrid(painter, m_LeftVal, m_RightVal, dd, len, h, rt, pt, fm, lscalelen, 6);
// 恢复原始网格数
m_pViewInfoLogmud->SetxGrid(originalXGrid);
m_pViewInfoLogmud->SetyGrid(originalYGrid);
// 绘制分界线 (0, 6) 到 (18, 0)
// 绘制分界线 (0, 6) 到 (18, 0)
painter->save();
QPen linePen;
linePen.setColor(QColor(192, 192, 192)); // 浅灰色
linePen.setWidth(2);
painter->setPen(linePen);
// 计算分界线的屏幕坐标
float x1 = 0.0f;
float y1 = 6.0f;
float x2 = 18.0f;
float y2 = 0.0f;
// X坐标转换
float screenX1 = rt.left() + dd + (x1 - timemin) * len / dtime;
float screenX2 = rt.left() + dd + (x2 - timemin) * len / dtime;
// Y坐标转换注意Y轴是反向的
float dval = m_RightVal - m_LeftVal;
if(dval == 0) dval = 1;
float screenY1 = pt1.y() + h - (y1 - m_LeftVal) * h / dval;
float screenY2 = pt1.y() + h - (y2 - m_LeftVal) * h / dval;
// 绘制分界线
painter->drawLine(QPointF(screenX1, screenY1), QPointF(screenX2, screenY2));
// 在分界线两侧添加标签
QFont labelFont = painter->font();
labelFont.setBold(true);
painter->setFont(labelFont);
painter->setPen(Qt::black);
// 火成岩标签 - 放在分界线左上方区域
float igneousX = rt.left() + dd + len * 0.15f; // X轴15%位置约5.25
float igneousY = pt1.y() + h * (1 - 8.0f/12.0f); // Y轴位置对应Y=8
QString igneousText = QString::fromLocal8Bit("火成岩");
QRectF igneousRect = fm.boundingRect(igneousText);
painter->drawText(QPointF(igneousX - igneousRect.width()/2, igneousY), igneousText);
// 沉积岩标签 - 放在分界线左下方区域
float sedimentaryX = rt.left() + dd + len * 0.1f; // X轴10%位置约3.5
float sedimentaryY = pt1.y() + h * (1 - 2.0f/12.0f); // Y轴位置对应Y=2
QString sedimentaryText = QString::fromLocal8Bit("沉积岩");
QRectF sedimentaryRect = fm.boundingRect(sedimentaryText);
painter->drawText(QPointF(sedimentaryX - sedimentaryRect.width()/2, sedimentaryY), sedimentaryText);
painter->restore();
// 绘制深度和轴标题
DrawDepthAndAxisLabels(painter, resultitem->depth, dd, w, h, rt, pt, fm, lscalelen, pCore,
"Fe+Mg %", "Na+K %");
// 绘制投点
DrawDataPoint(painter, resultitem->WH, resultitem->BH, timemin, timemax,
m_LeftVal, m_RightVal, dd, len, h, rt, pt1, AXIS_LINEAR);
// 绘制辅助线
painter->drawLine(QPointF(rt.left(), pt1.y()), QPointF(rt.left()+rt.width()/20, pt1.y()));
// 恢复原始坐标系设置
m_pViewInfoLogmud->SetLogarithmic(originalLogarithmic);
m_pViewInfoLogmud->SetTLogarithmic(originalTLogarithmic);
painter->restore();
}//判断火成岩-沉积岩的右括号
// 碳酸盐-砂泥岩图版
else if(resultitem->type == 12)
{
// 保存原始坐标系设置
int originalLogarithmic = m_pViewInfoLogmud->GetLogarithmic();
int originalTLogarithmic = m_pViewInfoLogmud->GetTLogarithmic();
// 临时设置为线性坐标系
m_pViewInfoLogmud->SetLogarithmic(AXIS_LINEAR);
m_pViewInfoLogmud->SetTLogarithmic(AXIS_LINEAR);
// 初始坐标轴范围
float timemin = 0.0f;
float timemax = 50.0f; // X轴最大值50 (Si %)
float m_LeftVal = 0.0f;
float m_RightVal = 50.0f; // Y轴最大值50 (Mg+Ca %)
// 检查X轴 (Si值)
if (resultitem->WH > timemax) {
// 将最大值扩展到5的倍数
timemax = ceil(resultitem->WH/5)*5;
}
// 检查Y轴 (Mg+Ca值)
if (resultitem->BH > m_RightVal) {
// 将最大值扩展到5的倍数
m_RightVal = ceil(resultitem->BH/5)*5;
}
float lval = m_LeftVal;
int Logarithmic = m_pViewInfoLogmud->GetLogarithmic();
float rval = m_RightVal;
// 重新计算X轴范围
float dtime = timemax - timemin;
if(dtime == 0) dtime = 1;
// 保存原始网格数
int originalXGrid = m_pViewInfoLogmud->GetxGrid();
int originalYGrid = m_pViewInfoLogmud->GetyGrid();
// 设置网格数
// X轴0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50 (间隔5共10个间隔)
m_pViewInfoLogmud->SetxGrid(10);
// Y轴0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50 (间隔5共10个间隔)
m_pViewInfoLogmud->SetyGrid(10);
// 绘制网格
DrawXAxisLinearGrid(painter, timemin, timemax, dd, len, h, rt, pt, pt1, fm, 10);
DrawYAxisLinearGrid(painter, m_LeftVal, m_RightVal, dd, len, h, rt, pt, fm, lscalelen, 10);
// 恢复原始网格数
m_pViewInfoLogmud->SetxGrid(originalXGrid);
m_pViewInfoLogmud->SetyGrid(originalYGrid);
// 绘制分界线 (0, 0) 到 (50, 50) - 45度对角线
painter->save();
QPen linePen;
linePen.setColor(QColor(192, 192, 192)); // 浅灰色
linePen.setWidth(2);
painter->setPen(linePen);
// 计算分界线的屏幕坐标
float x1 = 0.0f;
float y1 = 0.0f;
float x2 = 50.0f;
float y2 = 50.0f;
// 如果坐标范围扩展了,需要调整线的终点
if (timemax > 50.0f || m_RightVal > 50.0f) {
// 延长线到新的边界
float maxVal = std::max(timemax, m_RightVal);
x2 = maxVal;
y2 = maxVal;
}
// X坐标转换
float screenX1 = rt.left() + dd + (x1 - timemin) * len / dtime;
float screenX2 = rt.left() + dd + (x2 - timemin) * len / dtime;
// Y坐标转换注意Y轴是反向的
float dval = m_RightVal - m_LeftVal;
if(dval == 0) dval = 1;
float screenY1 = pt1.y() + h - (y1 - m_LeftVal) * h / dval;
float screenY2 = pt1.y() + h - (y2 - m_LeftVal) * h / dval;
// 绘制分界线
painter->drawLine(QPointF(screenX1, screenY1), QPointF(screenX2, screenY2));
// 在分界线两侧添加标签
QFont labelFont = painter->font();
labelFont.setBold(true);
painter->setFont(labelFont);
painter->setPen(Qt::black);
// 碳酸盐标签 - 放在对角线上方区域(左上方)
float carbonateX = rt.left() + dd + len * 0.2f; // X轴20%位置约10
// Y=30对应的屏幕位置
float carbonateY = pt1.y() + h * (1 - 30.0f/m_RightVal); // Y轴位置对应Y=30
QString carbonateText = QString::fromLocal8Bit("碳酸盐");
QRectF carbonateRect = fm.boundingRect(carbonateText);
painter->drawText(QPointF(carbonateX - carbonateRect.width()/2, carbonateY), carbonateText);
// 砂泥岩标签 - 放在对角线下方区域(右下方)
float sandstoneMudstoneX = rt.left() + dd + len * 0.7f; // X轴70%位置约35
// Y=20对应的屏幕位置
float sandstoneMudstoneY = pt1.y() + h * (1 - 20.0f/m_RightVal); // Y轴位置对应Y=20
QString sandstoneMudstoneText = QString::fromLocal8Bit("砂泥岩");
QRectF sandstoneMudstoneRect = fm.boundingRect(sandstoneMudstoneText);
painter->drawText(QPointF(sandstoneMudstoneX - sandstoneMudstoneRect.width()/2,
sandstoneMudstoneY), sandstoneMudstoneText);
painter->restore();
// 绘制深度和轴标题
DrawDepthAndAxisLabels(painter, resultitem->depth, dd, w, h, rt, pt, fm, lscalelen, pCore,
"Si %", "Mg+Ca %");
// 绘制投点
DrawDataPoint(painter, resultitem->WH, resultitem->BH, timemin, timemax,
m_LeftVal, m_RightVal, dd, len, h, rt, pt1, AXIS_LINEAR);
// 绘制辅助线
painter->drawLine(QPointF(rt.left(), pt1.y()), QPointF(rt.left()+rt.width()/20, pt1.y()));
// 恢复原始坐标系设置
m_pViewInfoLogmud->SetLogarithmic(originalLogarithmic);
m_pViewInfoLogmud->SetTLogarithmic(originalTLogarithmic);
painter->restore();
}//判断碳酸盐-砂泥岩的右括号
//泥岩-砂岩图版
else if(resultitem->type == 13)
{
// 保存原始坐标系设置
int originalLogarithmic = m_pViewInfoLogmud->GetLogarithmic();
int originalTLogarithmic = m_pViewInfoLogmud->GetTLogarithmic();
// 临时设置为线性坐标系
m_pViewInfoLogmud->SetLogarithmic(AXIS_LINEAR);
m_pViewInfoLogmud->SetTLogarithmic(AXIS_LINEAR);
// 固定坐标轴范围
float timemin = 20.0f; // X轴最小值20
float timemax = 47.0f; // X轴最大值47 (Si %)
float m_LeftVal = 0.0f;
float m_RightVal = 25.0f; // Y轴最大值25 (Al+Fe %)
float lval = m_LeftVal;
float rval = m_RightVal;
// 计算X轴范围
float dtime = timemax - timemin;
if(dtime == 0) dtime = 1;
// 保存原始网格数
int originalXGrid = m_pViewInfoLogmud->GetxGrid();
int originalYGrid = m_pViewInfoLogmud->GetyGrid();
// 设置网格数
m_pViewInfoLogmud->SetxGrid(6); // 20到47之间每5一格约6格
m_pViewInfoLogmud->SetyGrid(5); // 0到25每5一格5格
// 绘制网格 - 使用正确的起始值
DrawXAxisLinearGrid(painter, timemin, timemax, dd, len, h, rt, pt, pt1, fm, 6);
DrawYAxisLinearGrid(painter, m_LeftVal, m_RightVal, dd, len, h, rt, pt, fm, lscalelen, 5);
// 恢复原始网格数
m_pViewInfoLogmud->SetxGrid(originalXGrid);
m_pViewInfoLogmud->SetyGrid(originalYGrid);
// 绘制分界线 (20, 0) 到 (47, 25)
painter->save();
QPen linePen;
linePen.setColor(QColor(128, 128, 128)); // 灰色
linePen.setWidth(2);
painter->setPen(linePen);
// 计算分界线的屏幕坐标
float x1 = 20.0f;
float y1 = 0.0f;
float x2 = 47.0f;
float y2 = 25.0f;
// X坐标转换
float screenX1 = rt.left() + dd; // x1=20是起始点
float screenX2 = rt.left() + dd + len; // x2=47是结束点
// Y坐标转换注意Y轴是反向的
float screenY1 = pt1.y() + h; // y1=0是底部
float screenY2 = pt1.y(); // y2=25是顶部
// 绘制分界线
painter->drawLine(QPointF(screenX1, screenY1), QPointF(screenX2, screenY2));
// 在分界线两侧添加标签
QFont labelFont = painter->font();
labelFont.setBold(true);
painter->setFont(labelFont);
painter->setPen(Qt::black);
// 泥岩标签 - 放在左上方
QString mudstoneText = QString::fromLocal8Bit("泥岩");
painter->drawText(QPointF(rt.left() + dd + len * 0.25f, pt1.y() + h * 0.3f), mudstoneText);
// 砂岩标签 - 放在右下方
QString sandstoneText = QString::fromLocal8Bit("砂岩");
painter->drawText(QPointF(rt.left() + dd + len * 0.65f, pt1.y() + h * 0.7f), sandstoneText);
painter->restore();
// 绘制深度和轴标题
DrawDepthAndAxisLabels(painter, resultitem->depth, dd, w, h, rt, pt, fm, lscalelen, pCore,
"Si %", "Al+Fe %");
// 绘制投点
DrawDataPoint(painter, resultitem->WH, resultitem->BH, timemin, timemax,
m_LeftVal, m_RightVal, dd, len, h, rt, pt1, AXIS_LINEAR);
// 绘制辅助线
painter->drawLine(QPointF(rt.left(), pt1.y()), QPointF(rt.left()+rt.width()/20, pt1.y()));
// 恢复原始坐标系设置
m_pViewInfoLogmud->SetLogarithmic(originalLogarithmic);
m_pViewInfoLogmud->SetTLogarithmic(originalTLogarithmic);
painter->restore();
}//判断泥岩-砂岩的右括号
*/
painter->restore();
}
painter->restore();
}
return pt;
}
return pt;
}
// 绘制X轴对数刻度
void LogmudItemDrawer::DrawXAxisLogarithmicGrid(QPainter* painter, float timemin, float timemax,
float dd, float w, float h, QRectF rt, QPointF pt,
QFontMetrics& fm, float& lscalelen) const
{
float d1;
float lsc = timemin, rsc = timemax;
if(!IsFiniteNumber(lsc)||lsc <= 0) lsc = 0.1f;
if(!IsFiniteNumber(rsc)||rsc <= 0) rsc = lsc * 10.0f;
if(rsc <= lsc) rsc = lsc * 10.0f;
if(rsc/lsc > 100000000.0f) rsc = lsc * 100000000.0f;
float ddd = lsc;
float mm = lsc/ddd;
float x;
float logRange = log10(rsc/lsc);
if(!IsFiniteNumber(logRange)||qAbs(logRange)<1e-6f) return;
int safetyCounter = 0;
for (d1 = lsc; d1 <= rsc; d1 = ((int)(d1/mm+1.5f))*mm) // 循环生成刻度
{
if(++safetyCounter>20000) break;
if(!IsFiniteNumber(d1)||!IsFiniteNumber(mm)||qAbs(mm)<1e-20f) break;
QPen penGuide(QColor(220, 220, 220), 1);
painter->setPen(penGuide);
x = log10(d1/lsc)/logRange*w;
if (fmod(log10(d1), (float)1.0f) == 0.0f)
{
painter->save();
QPen penw = painter->pen();
float pww = penw.widthF();
if(pww <= 0) pww = 1.0f;
float pw = pww * 0.5f;
penw.setWidthF(pw);
painter->setPen(penw);
painter->drawLine(rt.left()+dd+x, pt.y(), rt.left()+dd+x, pt.y()+h);
painter->setPen(m_Color);// m_pViewInfoLogmud->GetColor());
QString cs = toString(d1);
QTransform transform;
transform.reset();
qreal rotatex=0;
qreal rotatey=0;
rotatex = rt.left()+dd+x;
rotatey = pt.y()+h+fm.height()/3;
//=============================================
QRectF tempRect,drawRect;
////===================层号旋转===========================
// 绘制刻度标签
transform = painter->worldTransform();
transform.translate(rotatex, rotatey);
transform.rotate(0);
transform.translate(-rotatex, -rotatey);
painter->setWorldTransform(transform);
QRectF textRect;
if(!cs.isEmpty())
{
tempRect = fm.boundingRect(cs);
if(lscalelen < tempRect.width()) lscalelen = tempRect.width();
textRect.setX(rotatex-tempRect.width()/2);
textRect.setY(rotatey);
textRect.setWidth(tempRect.width());
textRect.setHeight(tempRect.height());
painter->drawText(textRect, Qt::AlignHCenter|Qt::AlignVCenter, cs);
}
painter->restore();
}
else
{
painter->drawLine(rt.left()+dd+x, pt.y(), rt.left()+dd+x, pt.y()+h);
}
// 更新刻度计算参数
ddd = d1;
if(!IsFiniteNumber(ddd)||ddd<=0) break;
if(ddd < 1.0f)
{
int k=0;
while(ddd < 1.0f && ++k<20) ddd *= 10.0f;
}
else
{
int k=0;
while(ddd > 1.0f && ++k<20) ddd /= 10.0f;
if(ddd < 1.0f) ddd = ddd * 10.0f;
}
mm = d1/ddd;
if(!IsFiniteNumber(mm)||qAbs(mm)<1e-20f) break;
}
// 绘制边界线
painter->drawLine(rt.left()+dd, pt.y(), rt.left()+dd, pt.y()+h);
painter->drawLine(rt.left()+dd+w, pt.y(), rt.left()+dd+w, pt.y()+h);
}
// 绘制X轴线性刻度
void LogmudItemDrawer::DrawXAxisLinearGrid(QPainter* painter, float timemin, float timemax,
float dd, float len, float h, QRectF rt, QPointF pt,
QPointF pt1, QFontMetrics& fm, int fnum) const
{
for(int i = 0; i < fnum + 1; i++)
{
painter->save();
painter->setPen(m_CGrid);// m_pViewInfoLogmud->GetCGrid());
painter->drawLine(QPointF(rt.left()+dd+i*len/fnum, pt1.y()),
QPointF(rt.left()+dd+i*len/fnum, pt1.y()+h));
QString cs = toString(timemin+(timemax-timemin)/fnum*i);
painter->setPen(m_Color);// m_pViewInfoLogmud->GetColor());
QTransform transform;
transform.reset();
qreal rotatex=0;
qreal rotatey=0;
rotatex = rt.left()+dd+i*len/fnum;
rotatey = pt.y()+h+fm.height()/3;
//=============================================
QRectF tempRect,drawRect;
painter->setPen(m_Color);// m_pViewInfoLogmud->GetColor());
////===================层号旋转===========================
// 绘制刻度标签
transform = painter->worldTransform();
transform.translate(rotatex, rotatey);
transform.rotate(0);
transform.translate(-rotatex, -rotatey);
painter->setWorldTransform(transform);
QRectF textRect;
if(!cs.isEmpty())
{
tempRect = fm.boundingRect(cs);
textRect.setX(rotatex-tempRect.width()/2);
textRect.setY(rotatey);
textRect.setWidth(tempRect.width());
textRect.setHeight(tempRect.height());
painter->drawText(textRect, Qt::AlignHCenter|Qt::AlignTop, cs);
}
painter->restore();
}
}
// 绘制Y轴对数刻度
void LogmudItemDrawer::DrawYAxisLogarithmicGrid(QPainter* painter, float minVal, float maxVal,
float dd, float len, float h, QRectF rt, QPointF pt,
QFontMetrics& fm, float& lscalelen) const
{
float d1;
float lsc = minVal, rsc = maxVal;
if(!IsFiniteNumber(lsc)||lsc <= 0) lsc = 0.1f;
if(!IsFiniteNumber(rsc)||rsc <= 0) rsc = lsc * 10.0f;
if(rsc <= lsc) rsc = lsc * 10.0f;
if(rsc/lsc > 100000000.0f) rsc = lsc * 100000000.0f;
float ddd = lsc;
float mm = lsc/ddd;
float x;
float logRange = log10(rsc/lsc);
if(!IsFiniteNumber(logRange)||qAbs(logRange)<1e-6f) return;
int safetyCounter = 0;
for (d1 = lsc; d1 <= rsc; d1 = ((int)(d1/mm+1.5f))*mm)
{
if(++safetyCounter>20000) break;
if(!IsFiniteNumber(d1)||!IsFiniteNumber(mm)||qAbs(mm)<1e-20f) break;
QPen penGuide(QColor(220, 220, 220), 1);
painter->setPen(penGuide);
x = log10(d1/lsc)/logRange*h;
if (fmod(log10(d1), (float)1.0f) == 0.0f)
{
painter->save();
QPen penw = painter->pen();
float pww = penw.widthF();
if(pww <= 0) pww = 1.0f;
float pw = pww * 0.5f;
penw.setWidthF(pw);
painter->setPen(penw);
painter->drawLine(rt.left()+dd, pt.y()+h-x, rt.left()+dd+len, pt.y()+h-x);
painter->setPen(m_Color);// m_pViewInfoLogmud->GetColor());
QString cs = toString(d1);
QTransform transform;
transform.reset();
qreal rotatex=0;
qreal rotatey=0;
rotatex = rt.left();
rotatey = pt.y()+h-x;
//=============================================
QRectF tempRect,drawRect;
////===================层号旋转===========================
// 绘制刻度标签
transform = painter->worldTransform();
transform.translate(rotatex, rotatey);
transform.rotate(0);
transform.translate(-rotatex, -rotatey);
painter->setWorldTransform(transform);
QRectF textRect;
if(!cs.isEmpty() && m_isOneScale)//m_pViewInfoLogmud->GetisOneScale())
{
tempRect = fm.boundingRect(cs);
if(lscalelen < tempRect.width()) lscalelen = tempRect.width();
textRect.setX(rt.left());
textRect.setY(rotatey-tempRect.height()/2.0f);
textRect.setWidth(dd-fm.width("0")/2);
textRect.setHeight(tempRect.height());
painter->drawText(textRect, Qt::AlignRight|Qt::AlignVCenter, cs);
}
painter->restore();
}
else
{
painter->drawLine(rt.left()+dd, pt.y()+h-x, rt.left()+dd+len, pt.y()+h-x);
}
// 更新刻度计算参数
ddd = d1;
if(!IsFiniteNumber(ddd)||ddd<=0) break;
if(ddd < 1.0f)
{
int k=0;
while(ddd < 1.0f && ++k<20) ddd *= 10.0f;
}
else
{
int k=0;
while(ddd > 1.0f && ++k<20) ddd /= 10.0f;
if(ddd < 1.0f) ddd = ddd * 10.0f;
}
mm = d1/ddd;
if(!IsFiniteNumber(mm)||qAbs(mm)<1e-20f) break;
}
// 绘制边界线
painter->drawLine(rt.left()+dd, pt.y(), rt.left()+dd+len, pt.y());
painter->drawLine(rt.left()+dd, pt.y()+h, rt.left()+dd+len, pt.y()+h);
}
// 绘制Y轴线性刻度
void LogmudItemDrawer::DrawYAxisLinearGrid(QPainter* painter, float minVal, float maxVal,
float dd, float len, float h, QRectF rt, QPointF pt,
QFontMetrics& fm, float& lscalelen, int fnum) const
{
// 防止fnum为0
if(fnum <= 0) fnum = 1;
// 确保最大值大于最小值
if(maxVal <= minVal) maxVal = minVal + 1.0f;
for(int i = 0; i < fnum + 1; i++)
{
painter->save();
painter->setPen(m_CGrid);// m_pViewInfoLogmud->GetCGrid());
painter->drawLine(QPointF(rt.left()+dd, pt.y()+i*h/fnum),
QPointF(rt.left()+dd+len, pt.y()+i*h/fnum));
painter->setPen(m_Color);// m_pViewInfoLogmud->GetColor());
QString cs = toString(maxVal-(maxVal-minVal)/fnum*i);
QTransform transform;
transform.reset();
qreal rotatex=0;
qreal rotatey=0;
rotatex = rt.left();
rotatey = pt.y()+i*h/fnum;
//=============================================
QRectF tempRect,drawRect;
painter->setPen(m_Color);// m_pViewInfoLogmud->GetColor());
////===================层号旋转===========================
// 绘制刻度标签
transform = painter->worldTransform();
transform.translate(rotatex, rotatey);
transform.rotate(0);
transform.translate(-rotatex, -rotatey);
painter->setWorldTransform(transform);
QRectF textRect;
if(!cs.isEmpty() && m_isOneScale)//m_pViewInfoLogmud->GetisOneScale())
{
tempRect = fm.boundingRect(cs);
if(lscalelen < tempRect.width()) lscalelen = tempRect.width();
textRect.setX(rt.left());
textRect.setY(rotatey-tempRect.height()/2.0f);
textRect.setWidth(dd-fm.width("0")/2);
textRect.setHeight(tempRect.height());
painter->drawText(textRect, Qt::AlignRight|Qt::AlignVCenter, cs);
}
painter->restore();
}
}
//绘制深度和轴标题
void LogmudItemDrawer::DrawDepthAndAxisLabels(QPainter* painter, float depth, float dd, float w, float h,
QRectF rt, QPointF pt, QFontMetrics& fm,
float lscalelen,
const QString& xAxisTitle, const QString& yAxisTitle) const
{
painter->save();
// 设置黑色画笔
painter->setPen(Qt::black);
// 绘制深度值
QString cs = toString(depth);
cs += "";
float zw = fm.width(cs);
if(m_isBottom == 0) {
painter->drawText(QPointF(rt.left()+dd+(rt.width()-2*rt.width()*2/10-fm.width(cs))/2, pt.y()-fm.height()),
cs, Qt::AlignRight|Qt::AlignVCenter, 0);
}
else if(m_isBottom == 1) {
painter->drawText(QPointF(rt.left()+dd+(w-fm.width(cs))/2,
pt.y()+h+((m_bisHi ?2.3:(0/*pCore->GetFieldName().size()*/?0:1.5))+1)*fm.height()),
cs, Qt::AlignRight|Qt::AlignVCenter, 0);
}
else if(m_isBottom == 2) {
painter->drawText(QPointF(rt.left()+rt.width()/20, pt.y()-fm.height()/2),
cs, Qt::AlignRight|Qt::AlignVCenter, 0);
}
else if(m_isBottom == 3) {
painter->drawText(QPointF(rt.right()-fm.width(cs), pt.y()-fm.height()/2),
cs, Qt::AlignRight|Qt::AlignVCenter, 0);
}
// 绘制X轴标题
QString xTitle = xAxisTitle.isEmpty() ? m_TimeName : xAxisTitle;
if(!m_isOneScale && xAxisTitle.isEmpty()) xTitle = "";
painter->drawText(QPointF(rt.left()+dd+(w-fm.width(xTitle))/2,
pt.y()+h+((m_bisHi ?1.3:(m_isBottom==0?1:0))+1)*fm.height()),
xTitle, Qt::AlignRight|Qt::AlignVCenter, 0);
// 绘制Y轴标题
QString yTitle = yAxisTitle.isEmpty() ? m_CurveName : yAxisTitle;
// 如果提供了自定义Y轴标题则旋转绘制
if (!yAxisTitle.isEmpty()) {
QTransform transform;
transform = painter->worldTransform();
qreal rotatex = rt.left() + dd/3;
qreal rotatey = pt.y() + h/2 + fm.width(yTitle)/2;
transform.translate(rotatex, rotatey);
transform.rotate(-90);
transform.translate(-rotatex, -rotatey);
painter->setWorldTransform(transform);
painter->drawText(QPointF(rotatex, rotatey), yTitle);
// 恢复变换
transform.reset();
painter->setWorldTransform(transform);
}
else {
// 原有的多行Y轴标题绘制方式
yTitle.replace("\\n", "\n");
QStringList strs = yTitle.split("\n");
float mw = 0;
for(int i = 0; i < strs.size(); i++) {
if(mw < fm.width(strs.at(i))) mw = fm.width(strs.at(i));
}
for(int i = 0; i < strs.size(); i++) {
QRectF temp(rt.left()+dd-lscalelen-fm.width("0")/2-mw,
pt.y()+(h-strs.size()*fm.height())/2+i*fm.height()+fm.height(), mw, fm.height());
QTextOption op(Qt::AlignHCenter|Qt::AlignVCenter);
painter->drawText(temp, strs.at(i), op);
}
}
painter->restore();
}
// 绘制投点
void LogmudItemDrawer::DrawDataPoint(QPainter* painter, float wh, float bh, float timemin, float timemax,
float minVal, float maxVal, float dd, float len, float h,
QRectF rt, QPointF pt1, int logarithmic) const
{
// 保存当前绘图状态
painter->save();
// 重置变换,确保在设备坐标系中绘制
QTransform transform;
transform.reset();
painter->setWorldTransform(transform);
// 计算屏幕坐标
float pointX = 0;
float pointY = 0;
// X坐标转换(WH)
if (m_pViewInfoLogmud->GetTLogarithmic() == AXIS_LOGARITHMIC) {
// 对数坐标系
float safeMinX = timemin;
float safeMaxX = timemax;
if(!IsFiniteNumber(safeMinX) || safeMinX <= 0) safeMinX = 0.1f;
if(!IsFiniteNumber(safeMaxX) || safeMaxX <= safeMinX) safeMaxX = safeMinX * 10.0f;
float logRangeX = log10(safeMaxX) - log10(safeMinX);
if(!IsFiniteNumber(logRangeX) || qAbs(logRangeX) < 1e-6f) logRangeX = 1.0f;
float val = wh;
if (!IsFiniteNumber(val) || val <= 0) val = safeMinX;
if (val > safeMaxX) val = safeMaxX;
pointX = rt.left() + dd + (log10(val) - log10(safeMinX)) * len / logRangeX;
} else {
// 线性坐标系
float rangeX = timemax - timemin;
if(!IsFiniteNumber(rangeX) || qAbs(rangeX) < 1e-6f) rangeX = 1.0f;
pointX = rt.left() + dd + (wh - timemin) * len / rangeX;
}
// Y坐标转换(BH)
if (logarithmic == AXIS_LINEAR) {
// 线性坐标系
float rangeY = maxVal - minVal;
if(!IsFiniteNumber(rangeY) || qAbs(rangeY) < 1e-6f) rangeY = 1.0f;
pointY = (bh - minVal) / rangeY * h;
} else if (logarithmic == AXIS_LOGARITHMIC) {
// 对数坐标系
float val = bh;
if (!IsFiniteNumber(val) || val <= 0) val = 0.1f;
float lval = (minVal <= 0) ? log10(0.1f) : log10(minVal);
float rval = (maxVal <= 0) ? log10(0.1f) : log10(maxVal);
float rangeY = rval - lval;
if(!IsFiniteNumber(rangeY) || qAbs(rangeY) < 1e-6f) rangeY = 1.0f;
pointY = (log10(val) - lval) / rangeY * h;
}
if (pointY < 0) pointY = 0;
if (pointY > h) pointY = h;
pointY = pt1.y() + h - pointY;
// 设置投点样式
QPen pointPen;
pointPen.setColor(Qt::red);
pointPen.setWidth(2);
painter->setPen(pointPen);
painter->setBrush(Qt::red);
// 绘制投点(圆形)
float pointSize = 3.0f;
painter->drawEllipse(QPointF(pointX, pointY), pointSize, pointSize);
// 恢复绘图状态
painter->restore();
}