#pragma warning(push,0) #include #include #include #include #include #include "LogmudItemDrawer.h" #include #include #include #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(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 points; points.resize(n+1); float yval=0; int jj=0; for(int j=0;jtimemax) 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 legendItems; legendItems.append("A: 干气或水层气"); legendItems.append("B: 天然气 → 凝析油"); legendItems.append("C: 伴生气 → 油"); legendItems.append("D: 向氧化油过渡"); for(int i=0; idrawText(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 pointsBottom; QVector pointsLeft; QVector 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 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 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 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 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(xmaxX) 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>> valueAreaList; // 添加所有价值区 // 1. 泥岩 QVector 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>("泥岩", mudstone)); // 2. 含灰泥岩 QVector 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>("含灰泥岩", calcareous)); // 3. 含云泥岩 QVector 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>("含云泥岩", dolomitic)); // 4. 灰质泥岩 QVector 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>("灰质泥岩", calcareous2)); // 5. 云质泥岩 QVector 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>("云质泥岩", dolomitic2)); // 6. 泥灰岩 QVector 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>("泥灰岩", marlstone)); // 7. 泥云岩 QVector 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>("泥云岩", marlyDolomite)); // 8. 含泥灰岩 QVector 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>("含泥灰岩", argillaceousLimestone)); // 9. 含泥云岩 QVector 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>("含泥云岩", argillaceousDolomite)); // 10. 灰岩 QVector 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>("灰岩", limestone)); // 11. 云岩 QVector 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>("云岩", dolomite)); // 12. 含云灰岩 QVector 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>("含云灰岩", dolomiteLimestone)); // 13. 含灰云岩 QVector 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>("含灰云岩", calcareousDolomite)); // 14. 云质灰岩 QVector 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>("云质灰岩", dolomiticalLimestone)); // 15. 灰质云岩 QVector 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>("灰质云岩", calcDolomite)); // 绘制所有价值区域 QVector placedAreaLabelRects; auto IsAreaLabelOverlap = [&placedAreaLabelRects](const QRectF& rect)->bool { for(int idx=0;idxfont(); 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 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 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;offsetIdxrt.left()+dd+w|| labelRect.top()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(val) % 5 != 0) { painter->drawLine(x, yAxisPos, x, yAxisPos + 5); } // 每 5 单位画一次文字 if (static_cast(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(val) % 2 != 0) { painter->drawLine(xAxisPos - 5, y, xAxisPos, y); } // 每 2 单位画一次文字 if (static_cast(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() << 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(col); // 逻辑 X: 0 ~ 3 double logicY = DataOfLines[row][col]; // 逻辑 Y: 实际数据 // ---------- X轴(线性) ---------- float screenX = static_cast(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(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(col); // 逻辑 X: 0 ~ 3 double logicY = resultitem->RATION_Y[col]; // 逻辑 Y: 实际数据 // ---------- X轴(线性) ---------- float screenX = static_cast(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(); }