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

news2024/12/27 3:30:00

前文链接: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.coloradmin.cn/o/871681.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

项目介绍:《WeTalk》网页聊天室 — Spring Boot、MyBatis、MySQL和WebSocket的奇妙融合

目录 引言&#xff1a; 前言&#xff1a; 技术栈&#xff1a; 主要功能&#xff1a; 功能详解&#xff1a; 1. 用户注册与登录&#xff1a; 2. 添加好友 3. 实时聊天 4. 消息未读 5. 删除聊天记录 6. 删除好友 未来展望&#xff1a; 项目地址&#xff1a; 结语&am…

IDEA关闭项目,但是后台程序没有关闭进程(解决方案)

最近遇到一个很奇怪的问题&#xff0c;idea关闭项目后&#xff0c;系统进程没有杀死进程&#xff0c;再次执行的时候会提示端口占用&#xff0c;并提示Process exited with an error: 1 (Exit value: 1) 错误原因&#xff1a;应用程序关闭后&#xff0c;进程不能同步关闭 解决方…

Python 使用Hadoop 3 之HDFS 总结

Hadoop 概述 Hadoop 是一个由Apache 软件基金会开发的分布式基础架构。用户可以在不了解分布式底层细节的情况下&#xff0c;开发分布式程序&#xff0c;充分利用集群的威力进行高速运算和存储。 Hadoop 实现一个分布式文件系统&#xff08;Hadoop Distributed File Sy…

短肥网络的 RTT 敏感性

周二下班路上发了一则朋友圈&#xff1a; 长肥管道的特征和问题谈得够多了&#xff0c;但这里谈的是短肥管道&#xff0c;因为下面趋势&#xff0c;短肥管道才是未来大势&#xff1a; 云计算致使数据中心网络快速发展&#xff0c;而数据中心网络时延短&#xff0c;带宽大。CD…

尼科彻斯定理-C语言/Java

描述 验证尼科彻斯定理&#xff0c;即&#xff1a;任何一个整数m的立方都可以写成m个连续奇数之和。 例如&#xff1a; 1^31 2^335 3^37911 4^313151719 输入一个正整数m&#xff08;m≤100&#xff09;&#xff0c;将m的立方写成m个连续奇数之和的形式输出。&…

代码详解——Transformer

文章目录 整体架构Modules.pyScaledDotProductAttention SubLayers.pyMultiHeadAttentionPositionwiseFeedForward Layers.pyEncoderLayerDecoderLayer Models.pyget_pad_maskget_subsequent_maskPositionalEncodingEncoderDecoderTransformer 整体架构 源码地址&#xff08;py…

传输控制协议TCP

目录 TCP报文格式 TCP的特点 TCP原理: 1.确认应答机制 2.超时重传机制 3.连接管理机制 建立连接 ​编辑关闭连接 4.滑动窗口机制 ​5.流量控制 6.拥塞控制 7.延迟应答 8.捎带应答 TCP报文格式 1.源端口号:发送端的哪一个端口发出的 2.目的端口号:接收端的哪一个端…

【深度学习】遗传算法[选择、交叉、变异、初始化种群、迭代优化、几何规划排序选择、线性交叉、非均匀变异]

目录 一、遗传算法二、遗传算法概述2.1 选择2.2 交叉2.3 变异 三、遗传算法的基本步骤3.1 编码3.2 初始群体的生成3.3 适应度评估3.4 选择3.5 交叉3.6 变异3.7 总结 四、遗传算法工具箱4.1 initializega4.2 ga4.3 normGeomSelect4.4 arithXover4.5 nonUnifMutation 五、遗传算法…

【Transformer】自注意力机制Self-Attention | 各种网络归一化Normalization

1. Transformer 由来 & 特点 1.1 从NLP领域内诞生 "Transformer"是一种深度学习模型&#xff0c;首次在"Attention is All You Need"这篇论文中被提出&#xff0c;已经成为自然语言处理&#xff08;NLP&#xff09;领域的重要基石。这是因为Transfor…

苹果电脑 Java切换版本

效果 1、安装 Java1.8和Java11 直接官网下载并安装 2、安装后的文件 /资源库/Java/JavaVirtualMachines/ 3、修改配置文件 vi ~/.bash_profile#java export JAVA_8_HOME"/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home" alias jdk8expor…

大语言模型(LLM)与 Jupyter 连接起来了

现在&#xff0c;大语言模型&#xff08;LLM&#xff09;与 Jupyter 连接起来了&#xff01; 这主要归功于一个名叫 Jupyter AI 的项目&#xff0c;它是官方支持的 Project Jupyter 子项目。目前该项目已经完全开源&#xff0c;其连接的模型主要来自 AI21、Anthropic、AWS、Co…

信号调制原理演示,模拟和数字调制技术大比拼

【中英双语字幕】信号调制原理演示&#xff0c;模拟和数字调制技术大比拼&#xff01;_哔哩哔哩_bilibili

Filament for Android 编译搭建(基于Ubuntu20.04系统)

一、Filament 源代码下载 github下载地址&#xff1a; 2、安装clang 我是直接安装clang-10 Ubuntu 20.04 &#xff0c;sudo apt install clang 命令默认就是clang-10 $sudo apt-get install clang-10 # 安装 AST.h 等头文件 $sudo apt-get install libclang-10-dev $sudo …

大语言模型:LLM的概念是个啥?

一、说明 大语言模型&#xff08;维基&#xff1a;LLM- large language model&#xff09;是以大尺寸为特征的语言模型。它们的规模是由人工智能加速器实现的&#xff0c;人工智能加速器能够处理大量文本数据&#xff0c;这些数据大部分是从互联网上抓取的。 [1]所构建的人工神…

期权定价模型系列【3】—Delta动态对冲

Delta动态对冲 本文章主要介绍常见的delta对冲概念&#xff0c;具体的delta动态对冲代码可以参考【期权量化】专栏同名文章 专栏地址&#xff1a; http://t.csdn.cn/obNflhttp://t.csdn.cn/obNfl 1.前言 期权交易有四种基本交易方式&#xff1a;买入看涨期权、卖出看涨期权、买…

Linux基础知识学习

一、i.mx6ull交叉编译QT项目 1、步骤 2、安装交叉编译链 使能交叉编译链&#xff0c;使能刚安装的编译器&#xff0c;不然还是老版本的 source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi 3、命令行交叉编译QT项目 wandzhangwa…

Redis系列(二):深入解读Redis的两种持久化方式

博客地址&#xff1a;blog.zysicyj.top Redis为什么要引入持久化机制 Redis引入持久化机制是为了解决内存数据库的数据安全性和可靠性问题。虽然内存数据库具有高速读写的优势&#xff0c;但由于数据存储在内存中&#xff0c;一旦服务器停止或崩溃&#xff0c;所有数据将会丢失…

由于找不到vcruntime140_1.dll,无法继续执行代码的常见解决方法

在遇到vcruntime140_1.dll丢失的问题时&#xff0c;我对于计算机的运行状况感到非常困扰。这个错误导致我无法正常运行某个应用程序或游戏&#xff0c;给我带来了很多不便。然而&#xff0c;在修复这个问题的过程中&#xff0c;我学到了一些有用的知识和技巧&#xff0c;下面就…

tkinter+爬虫+pygame实现音乐播放器

文章目录 前文安装模块示意图爬虫完整代码pygametkinter完整代码结尾前文 本文将涉及爬虫(数据的获取),pygame(音乐播放器),tkinter(界面显示),将他们汇聚到一起制造一个音乐播放器,欢迎大家的订阅。 安装模块 pip install requests,parsel,lxpy,pygame 示意图

volatile用法详解(c语言)

前言 volatile是易变的、不稳定的意思。或许你没见过这个关键字&#xff0c;但它的的确确存在着。 volatile作用 保持内存可见性 volatile关键字和const 一样是一种类型修饰符,变量可以被某些编译器未知的因素更改,比如操作系统、硬件或者其他线程等,遇到这个关键字声明的变量…