logplus/logPlus/LogmudItemDrawer.cpp

3093 lines
146 KiB
C++
Raw Normal View History

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