赞
踩
在平面上,格子坐标通常是个二维坐标(X,Y),但是二维坐标有很多不方便的地方,且如果作为键值,其取值效率不高。因此大部分情况下,需要将二维坐标转换成ID来使用(且能从ID转换回坐标)。
常用的方式就是X*N+Y,N为一个足够大的数。但是这种方式有问题,其只能支持全正数或者全负数,一旦有正有负,就会坐标转换失败。因此需要一种较为便捷的算法,能将二维坐标映射成ID,且能互相转换。
基本原理如下图所示:
这就是ID的生成顺序,以一个螺旋形状进行生成。
这种生成方式的优点之一,便是可以仅仅通过转换出来的ID就能判定其里坐标原点的距离,存数组的时候可以视作有序。缺点便是其性能并不是最优。
原理没什么好说的,就是纯计算。直接上代码:
- public int ToInt(Vector2Int grid)
- {
- if (grid.x == 0 && grid.y == 0) return 0;
-
- int k = math.max(math.abs(grid.x), math.abs(grid.y));
- if (grid.x > grid.y)
- return 4 * k * k + 1 + 2 * k + grid.x + grid.y;
- else
- return 4 * k * k + 1 - 2 * k - grid.x - grid.y;
- }
ID转换回坐标略复杂一些,代码如下:
- public Vector2Int GetMapGrid(int index)
- {
- if (index == 0) return Vector2Int.zero;
- float sqrtX = math.sqrt(index);
- int k = (int)((sqrtX + 1) / 2);
- if (sqrtX > 2 * k)
- {
- int xAy = index - (4 * k * k + 1) - 2 * k;
- if (xAy < 0)
- {
- int y = -1 * k;
- int x = xAy - y;
- return new Vector2Int(x, y);
- }
- else
- {
- int x = k;
- int y = xAy - x;
- return new Vector2Int(x, y);
- }
- }
- else
- {
- int xAy = (4 * k * k + 1) - index - 2 * k;
- if (xAy < 0)
- {
- int x = -k;
- int y = xAy - x;
- return new Vector2Int(x, y);
- }
- else
- {
- int y = k;
- int x = xAy - y;
- return new Vector2Int(x, y);
- }
- }
- }
当然,还有一种其他的方法可以实现二维坐标转ID。原理简单,就是用一个long(int64)来储存,前32存x,后32位存y。这种处理方式很重要的一点,就是要避免进行加减法计算,只能使用位运算进行拼接。
代码如下:
- public long GetID(int q, int r)
- {
- long rt = (long)q << 32;
- rt = rt | (r & 0xffffffff);
- return rt;
- }
-
- public Vector2Int GetCoordinate(long id)
- {
- int x = (int)(id >> 32);
- int y = (int)id;
- return new Vector2Int(x, y);
- }
这个方法的缺点,就是转换后的值会变得特别大,而且不能仅通过观察数值大小就能确定其距离坐标原点的远近。
优点是理解容易,且性能更佳。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。