当前位置: 首页 > news >正文

QGraphicsView实现简易地图5『经纬网格』

前文链接:QGraphicsView实现简易地图4『局部加载-地图漫游』
由于GCJ02 Web 墨卡托投影 纬度并不随像素等分,且两极跨度较大,因此本次演示采用的经纬网等分逻辑为等分像素。同等像素跨度之间,两级纬度变化较小,越靠近赤道附近纬度变化越大。以下将提供实现此需求的核心代码。
1、动态演示效果

2、静态展示图片
在这里插入图片描述

核心代码

void MapView::showGraticules()
{// 计算等分像素后的经纬度步长int gridCount = MapUtility::graticulesGridCount(m_curLevel);int mapSideCount = apUtility::mapSideCount(m_curLevel);double perLon = PIXMAP_SIZE * mapSideCount * 1.0 / gridCount;double perLat = perLon;// 计算呈现的瓦片地图左上角和右下角的场景坐标QPoint topLeftScenePos(m_topLeftTileCoord.x * PIXMAP_SIZE, m_topLeftTileCoord.y * PIXMAP_SIZE);QPoint bottomRightScenePos((m_bottomRightTileCoord.x + 1) * PIXMAP_SIZE, (m_bottomRightTileCoord.y + 1) * PIXMAP_SIZE);// 计算经纬线覆盖范围,此处采用的逻辑是经纬网覆盖区域>=呈现的瓦片地图区域int leftGridIndex = qFloor(topLeftScenePos.x() / perLon);int rightGridIndex = qCeil(bottomRightScenePos.x() / perLon);int topGridIndex = qFloor(topLeftScenePos.y() / perLat);int bottomGridIndex = qCeil(bottomRightScenePos.y() / perLat);if (leftGridIndex < 0)leftGridIndex = 0;if (rightGridIndex > gridCount)rightGridIndex = gridCount;if (topGridIndex < 0)topGridIndex = 0;if (bottomGridIndex > gridCount)bottomGridIndex = gridCount;// 视口宽度和高度int vw = viewport()->width();int vh = viewport()->height();// 场景宽度和高度int sw = MapUtility::sceneSize(m_curLevel);int sh = sw;// 视口右下角对应场景坐标QPointF bottomRightViewToScenePos = mapToScene(viewport()->rect().bottomRight());// 经纬网线条颜色、文本颜色QColor gridLineColor(255, 163, 70);QColor textColor(Qt::white);// 绘制经纬网:纬度线for (int row = topGridIndex; row <= bottomGridIndex; ++row){	// 纬度线double sceneY = row * perLat;QGraphicsLineItem *item = m_scene->addLine(topLeftScenePos.x(), sceneY, bottomRightScenePos.x(), sceneY);item->setPen(QPen(gridLineColor, 1, Qt::DotLine));item->setZValue(50);m_vecGraticulesItems.append(item);// 纬度文本double lat = MapUtility::latFromSceneY(sceneY, m_curLevel);QGraphicsTextItem *textItem = m_scene->addText(CommonUtility::convertToDMSLatSymbol(lat));textItem->setDefaultTextColor(Qt::white);QFont font = textItem->font();font.setFamily("微软雅黑");textItem->setFont(font);// 调整文本位置QRectF textBoundingRect = textItem->boundingRect();int sceneX = sw <= vw ? bottomRightScenePos.x() : bottomRightViewToScenePos.x();textItem->setPos(sceneX - textItem->boundingRect().width(), sceneY - textBoundingRect.height() / 2);m_vecGraticulesTextItems.append(textItem);}// 绘制经纬网:经度线for (int col = leftGridIndex; col <= rightGridIndex; ++col){// 经度线double sceneX = col * perLon;QGraphicsLineItem *item = m_scene->addLine(sceneX, topLeftScenePos.y(), sceneX, bottomRightScenePos.y());item->setPen(QPen(gridLineColor, 1, Qt::DotLine));item->setZValue(50);m_vecGraticulesItems.append(item);// 经度文本double lon = MapUtility::lonFromSceneX(sceneX, m_curLevel);QGraphicsTextItem *textItem = m_scene->addText(CommonUtility::convertToDMSLonSymbol(lon));textItem->setDefaultTextColor(Qt::white);QFont font = textItem->font();font.setFamily("微软雅黑");textItem->setFont(font);// 调整文本位置QRectF textBoundingRect = textItem->boundingRect();int sceneY = sh <= vh ? bottomRightScenePos.y() : bottomRightViewToScenePos.y();textItem->setPos(sceneX - textBoundingRect.width() / 2, sceneY - textItem->boundingRect().height());m_vecGraticulesTextItems.append(textItem);}
}

辅助代码

void CommonUtility::convertToDMS(double value, int &d, int &m, int &s)
{d = (int)(value);                       m = (int)((value - d) * 60);s = (int)(((value - d) * 60 - m) * 60);// 四舍五入float e = ((value - d) * 60 - m) * 60 - s;if (5 <= (int)(e * 10))s += 1;// 秒进位if (60 == s){s = 0;m += 1;}// 分进位if (60 == m){m = 0;d += 1;}
}QString CommonUtility::convertToDMS(double value)
{int d, m, s;convertToDMS(value, d, m, s);QString strM = QString::number(m).rightJustified(2, '0');QString strS = QString::number(s).rightJustified(2, '0');return QString("%1°%2′%3″").arg(d).arg(strM).arg(strS);
}QString CommonUtility::convertToDMSLonSymbol(double value)
{return QString("%1%2").arg(convertToDMS(fabs(value))).arg(value > 0 ? "E" : (value != 0 ? "W" : ""));
}QString CommonUtility::convertToDMSLatSymbol(double value)
{return QString("%1%2").arg(convertToDMS(fabs(value))).arg(value > 0 ? "N" : (value != 0 ? "S" : ""));
}
http://www.lryc.cn/news/121667.html

相关文章:

  • RestTemplate 请求转发异常 ERR_CONTENT_DECODING_FAILED 200 (OK)
  • 用python实现一个异或计算器
  • Sketch打不开AI文件?转换方法在这里
  • 小游戏扫雷实现教学(详解)
  • 04 mysql innodb record
  • Centos7安装Docker
  • Vue中如何更好地封装组件?
  • C语言的链表的相关操作
  • Python3中typing模块
  • C语言自动抓取淘宝商品详情网页数据,实现轻松高效爬虫
  • 数据结构---跳表
  • 为什么Tomcat的NIO在读取body时要模拟阻塞?
  • 26 | 谷歌应用APP数据分析
  • BFS 五香豆腐
  • opencv实战项目 手势识别-手势控制键盘
  • 1.作用域
  • 黑马B站八股文学习笔记
  • 前端常用的上传下载文件的几种方式,直接上传、下载文件,读取.xlsx文件数据,导出.xlsx数据
  • FPGA应用学习笔记--时钟域的控制 亚稳态的解决
  • AirServer是什么软件,手机屏幕投屏电脑神器
  • 如何使用 AT+WEBSERVER 指令实现自定义的 Webserver html 网页配网
  • 期权定价模型系列【4】—期权组合的Delta-Gamma-Vega中性
  • k8sday02
  • 黑马头条项目学习--Day2: app端文章查看,静态化freemarker,分布式文件系统minIO
  • 特语云用Linux和MCSM面板搭建 我的世界基岩版插件服 教程
  • 2023.8
  • CSV文件编辑器——Modern CSV for mac
  • 全国各地区数字经济工具变量-文本词频统计(2002-2023年)
  • MacOS安装RabbitMQ
  • 关于selenium 元素定位的浅度解析