【瓦片地图】瓦片地图坐标转换
瓦片地图坐标转换
目录
瓦片地图坐标转换
一、前言
二、定义
二、矩形瓦片
三、菱形瓦片
1.斜菱形瓦片
2.正菱形瓦片
四、点在菱形内判断
一、前言
常见的瓦片地图有矩形、菱形、正六边形几种。此文章主要讨论菱形瓦片,也就是大家常说的2.5D,斜45度瓦片地图。比如《红警2》、《帝国时代2》都是采用这种技术。
严格来说,瓦片的角度并不是45度。因为为了美术作图方便,图片的宽高比一般为2:1,如下图所示,它的实际角度为arctan(1/2),不过这个数值对我们不重要。正如鱼香肉丝没有鱼一般,叫它45度瓦片也无妨,由于它是一个菱形,所以这里我们称它为菱形瓦片。
或许有人认为任意角度的瓦片都是可以的,其实不然,因为我们要考虑线条锯齿的画法,如果采用非整数比,则线条不是规律的(非像素游戏或许可以试试)。所以最常见的比例为2:1,其次是1:1。
还有一个问题,我们观察菱形的四分之一部分,它将一个矩形一分为二。我们当然期望它是平分的,然而这根本做不到,因为它不是理论的对角线。对于正方形瓦片来说,边缘是不会重叠的。而菱形瓦片不可避免的边缘存在重叠。
二、定义
我们定义地图上的一个点为世界(World)坐标,它是连续的,用浮点数表示。然后格子的索引叫地图(Map)坐标,它是离散的,用有符号整数表示。不过这里地图坐标的取值未考虑负数,如要使用负数的地图坐标则需要对代码略微修改。
比如下图的p点,我们假设格子宽10像素。则其世界坐标为(54,67),而地图坐标为(5,6)。
二、矩形瓦片
矩形瓦片的代码很简单,如下:
//! 矩形瓦片地图
template<Vector2 TILE_SIZE>
class Rectangle
{
public:/*** @brief 地图坐标 -> 世界坐标*/constexpr Vector2 Map2World(const Point& xy){return toVector2(xy) * TILE_SIZE;}/*** @brief 世界坐标 -> 地图坐标*/constexpr Point World2Map(const Vector2& pos){return toPoint(pos / TILE_SIZE);}
};
三、菱形瓦片
1.斜菱形瓦片
这里的斜指的是,整个地图拼出来是斜着的,也是一个菱形,如下图所示(这是常用的算法):
我们令x'y'为地图(格子)坐标,xy为世界(像素)坐标,其中wh为瓦片宽高,则有如下关系:
上面这个式子通过简单的变换,就可以得出:
转换代码如下,这里就体现出了将瓦片大小(TILE_SIZE)作为模板的好处了,其中除2的操作会自动合并为常量表达式,世界坐标到地图坐标的转换其中加了0.5,是为了四舍五入。
//! 斜45度瓦片地图
template<Vector2 TILE_SIZE>
class DiamondSlant
{
public:/*** @brief 地图坐标 -> 世界坐标*/constexpr Vector2 Map2World(const Point& xy){return { (xy[1] + xy[0]) * TILE_SIZE[0] / 2.0, (xy[1] - xy[0]) * TILE_SIZE[1] / 2.0};}/*** @brief 世界坐标 -> 地图坐标*/constexpr Point World2Map(const Vector2& pos){Vector2 xy_div = pos / TILE_SIZE;return toPoint(Vector2{ xy_div[0] - xy_div[1] + 0.5, xy_div[0] + xy_div[1] - 0.5 });}
};
2.正菱形瓦片
下面这种整体也是一个矩形,它的特点是x轴移动瓦片宽度,y轴只移动半个瓦片高度,当y为奇数时,x再往右移动半个瓦片宽度。(有些文章是y为偶数时x移动,原理相同)
容易得到,从格子坐标到世界坐标,如下:
当y为偶数时:
当y为奇数时:
这里出现和上面不一样的事了,无法简单的逆推公式来表示x'y'。因为通过世界(像素)坐标无法轻松得到它的地图(格子)坐标的y是奇数还是偶数。
从格子坐标到世界坐标的代码如下:
/**
* @brief 地图坐标 -> 世界坐标
*/
constexpr Vector2 Map2World(const Point& xy)
{Vector2 pos = { TILE_SIZE[0] * xy[0] , TILE_SIZE[1] / 2 * xy[1] };if (xy[1] % 2 != 0){//奇数行向右偏移 w / 2pos[0] += TILE_SIZE[0] / 2;}return pos;
}
而从世界坐标到格子坐标则比较麻烦了,如下,我们划分网格:
明显格子大小为(w,h),记世界坐标pos所在的格子为p,则有:
来看单个划分网格内,如下:
设瓦片格子坐标为xy,则当 pos在菱形内时,有:
当 pos在菱形外时,四个角则分别判断:右下角偏移(0,1);左下角偏移(-1,1);左上角偏移(-1,-1);右上角偏移(0,-1)。
所以最终实现代码如下:
//! 平菱形瓦片地图
template<Vector2 TILE_SIZE>
class DiamondFlat
{
public:/*** @brief 地图坐标 -> 世界坐标*/constexpr Vector2 Map2World(const Point& xy){Vector2 pos = { TILE_SIZE[0] * xy[0] , TILE_SIZE[1] / 2 * xy[1] };if (xy[1] % 2 != 0){//奇数行向右偏移 w / 2pos[0] += TILE_SIZE[0] / 2;}return pos;}/*** @brief 世界坐标 -> 地图坐标*/constexpr Point World2Map(const Vector2& pos){constexpr Vector2 TILE_SIZE_HALF = TILE_SIZE / 2.0;//四分之一矩形面积constexpr real s = Each::AccumulateMul(TILE_SIZE_HALF);//先计算矩形下标Point p = toPoint(pos / TILE_SIZE);//在矩形内坐标Vector2 p1 = pos - toVector2(p) * TILE_SIZE - TILE_SIZE_HALF;//点围成矩形面积real sp = abs(p1[0] * TILE_SIZE_HALF[1]) + abs(p1[1] * TILE_SIZE_HALF[0]);p[1] *= 2;if (s < sp){if (p1[0] > 0 && p1[1] > 0)return p + Point{ 0, 1 };else if (p1[0] < 0 && p1[1] > 0)return p + Point{ -1, 1 };else if (p1[0] < 0 && p1[1] < 0)return p + Point{ -1, -1 };else if (p1[0] > 0 && p1[1] < 0)return p + Point{ 0, -1 };elsereturn p;}else{return p;}}
};
四、点在菱形内判断
如下图所示,以菱形中心为原点建立坐标系:
当p点在菱形上时,红绿区域面积相等(对角线平分面积),所以:
(红色区域加了两次,将其中变成一个绿色区域)
则当p点在菱形外时,;在菱形内时。
源码位置:DND3D: 基于C++20与标准库的工具集
讨论群:818038139
by略游 于2022-06-14
【瓦片地图】瓦片地图坐标转换相关推荐
- GIS地图瓦片、坐标转换基本概念
什么是地图瓦片? 地图瓦片是包含了一系列比例尺.一定地图范围内的地图切片文件.地图瓦片按照金字塔结构组织,每张瓦片都可通过级别.行列号唯一标记.在平移.缩放地图时,浏览器根据金字塔规则,计算出所需的瓦 ...
- 地图瓦片相关学习总结
瓦片地图 瓦片地图金字塔模型是一种多分辨率层次模型,从瓦片金字塔的底层到顶层,分辨率越来越低,但表示 的地理范围不变. 中文名 瓦片地图 模 型层次模型 软 件ArcGIS软件 发 ...
- 高德地图加载谷歌地图瓦片
简介 苦逼外业实验需要用到无人机采集数据,遂利用高德地图SDK和DJI Mobile SDK开发了一款无人机航线规划软件.当地也不算偏僻,然而高德卫星地图缩放等级约为16,无法满足作业需求.调查了其他 ...
- 国内主要地图瓦片坐标系定义及计算原理
国内主要地图瓦片坐标系定义及计算原理 作者 CntChen 关注 2016.05.10 20:05* 字数 3144 阅读 1571评论 0喜欢 9 本文将介绍瓦片坐标相关知识,并提供高德地图.百度地 ...
- 瓦片地图服务与地图瓦片原理
本文字数:9099字 预计阅读时间:25分钟 这里,首先我们从概念出发,搞清楚瓦片地图服务以及地图瓦片的原理,读起来似乎有点拗口,但是从字面上看得出它们必定拥有着区别与联系,前者是WebGIS中的一个 ...
- SuperMap GIS基础软件地图瓦片问题QA
目录 一.地图瓦片存储.原理.结构介 1.1 不同存储类型对比 1.2 不同存储结构的存储示意图 2.1 目录结构说明 二.生成瓦片流程详解 1.海量影像瓦片 2.矢量瓦片 三.项目案例分享 1.X ...
- 翻译:Bing地图瓦片体系
Bing Maps Tile System Bing地图瓦片体系 原文链接:http://msdn.microsoft.com/en-us/library/bb259689.aspx Bing Map ...
- python下载谷歌地图瓦片_python获取bing地图发布自己的TMS服务(一)下载瓦片
部分结果 bing地图瓦片使用QuadKey作为命名方式. QuadKey简介 如何计算quadkey 在给定level下,把行号tileY和列号tileX转换为2进制,然后行列交叉存储,再转换为4进 ...
- 高德离线地图瓦片坐标偏移纠偏
对于地图坐标偏移,以leaflet为例,有如下解决办法 方法1.修改leaflet源码,解决地图坐标偏移问题 方法2.将点位真实的经纬度经过偏移算法,添加到加密的地图上 方法3.直接对离线地图瓦片进行 ...
- 腾讯、百度、高德、谷歌、天地图地图瓦片
以下是各地图的瓦片地图地址,可以在QGIS中加载,也可以在openlayer或leaflet前端页面中加载. 腾讯.百度.高德,加上谷歌和天地图应该足够用了.腾讯.高德是GCJ02坐标系,百度是BD0 ...
最新文章
- 你的裸照,一键生成,令人害怕的不是算法,是人心!
- 天软考c语言,软考中C语言试题问答精选
- Cannot unwrap to requested type [javax.sql.DataSource]
- rt-thread 自动初始化机制分析-关于编译链接及段信息
- java激励_激励---201218(激励总结)
- Private Data Manipulation in Optimal Sponsored Search Auction
- Google Chrome调试js代码
- python-jieba分词模块
- 20 个百无一用的 Firefox 扩展
- S1304第一本书内测测试分析
- Facebook广告投放有什么策略?
- express+mysqle
- Altium AD20原理图元件自动编号,位号重新排序
- 使用javadoc命令制作帮助文档(API)
- 通过两个队列实现一个栈(C语言)
- 无法复制文件到U盘解决办法
- Android 蓝牙 inquiry、inquiry scan、page、page scan等概念解析
- 联发科Helio X23/27十核发布:性能大提升/优化双摄
- 四周无人机的姿态解算(2)
- [技术讨论]关于单片机延时的实现讨论
热门文章
- 思科交换机配置试题_思科交换机基本配置
- Matplotlib系列(三):坐标轴变换及注释
- matlab 马氏距离 实例,MATLAB求马氏距离(Mahalanobis distance)
- 个人做代理记账如何接活
- 编译原理基本概念和术语
- luogu p1330封锁阳光大学
- 记学习量化投资 企业估值
- 某用户的计算机最近运行速度明显变慢,电脑运行速度慢,详细教您电脑运行速度变得越来越慢如何解决...
- Windows的13个版本的区别,企业版、教育版、专业版、工作站版、SE版的主要区别
- VScode 亮暗 高对比度 主题推荐