根据经纬度坐标计算NDS标准下的格网ID

前言

一、NDS是如何划分格网并编码的

这里直接引用原文。
Navigation Data Standard uses WGS 84, the World Geodetic System dating from 1984, as the standard coordinate reference system for representing latitude and longitude of objects. WGS 84 defines a fixed global reference frame for the whole earth for use in geodesy and navigation. By using this standard coordinate reference system, it is possible to uniquely identify any point on the Earth’s surface – except the North Pole – by two numbers, the x-coordinate and the y-coordinate of the point, where x corresponds to the longitude and y to the latitude.
坐标编码
For coding coordinates, a scaling factor is applied so that 360° correspond to 232, to exhaust the full range of 32 bit signed integers. In NDS, a coordinate unit corresponds to 90/230 degrees of longitude or latitude. Longitudes range between –180° and +180° and latitudes between –90° and +90°. Hence, coordinate values are in the range of –231≤ x < 231 for longitudes and–230≤ y < 230 for latitudes. This means that for latitudes 31 bits are sufficient. The origin of the coordinate system is the intersection of the WGS 84-0-meridian and the equator.The intention of this encoding is to represent the x-coordinate as signed 32-bit integers: x = x31 x30…x1 x0 and the y-coordinate as signed 31-bit integers: y = y30…y1 y0 with x31 and y30 as the most significant bits and x0 and y0 as the least significant bits.
Morton码介绍
From a coordinate, which is defined by two integer values for longitude (x) and latitude (y), the Morton code can be derived, which is a single number. Thus, two dimensions are mapped into one dimension. To be more precise, for a given coordinate with x = x31 x30…x1 x0 and y = y30…y1 y0the Morton code c is given by the 63-bit integerc = x31 y30 x30…y1 x1 y0 x0that results from interleaving the bits of the x- and y-coordinate, hence, 0 ≤ c < 263. If stored in a 64-bit integer, the Morton code c is prefixed with a 0 bit, thus always positive.If items are ordered according to their Morton code, we speak of a Morton order.
地图数据分层
The highest level in a database is labeled level 0. The lowest level is labeled level 15. Not all levels need to be available in a database.Navigation Data Standard uses level 13 for the most detailed routing data. For map display, however, levels below level 13 can be added. For example, it might be useful to store a detailed city map on level 14.
level 0:
在这里插入图片描述
level 1:
在这里插入图片描述
level 2:
在这里插入图片描述

二、计算格网ID的具体实现

直接上代码:

void ConvertXYToRowCol(int64_t x, int64_t y, uint8_t levelId, int32_t &col, int32_t &row)
{
    const int64_t NDS_180_DEGREES = (int64_t)1 << 31;
    const int64_t NDS_360_DEGREES = (int64_t)1 << 32;
    if (x < 0)
    {
        x += NDS_360_DEGREES;
    }
    if (y < 0)
    {
        y += NDS_180_DEGREES;
    }
    int32_t tileSizeFac = 31 - levelId;

    col = (int32_t)(x >> tileSizeFac);
    row = (int32_t)(y >> tileSizeFac);
}

void CalcMortonCodeToRowCol(uint32_t meshId, uint32_t &row, uint32_t &col)
{
    int32_t bit = 1;
    for (int32_t i = 0; i < 32; i++)
    {
        col |= ((meshId & bit) >> (i * 2) << i);
        bit <<= 1;
        row |= ((meshId & bit) >> (i * 2 + 1) << i);
        bit <<= 1;
    }
}

uint32_t ConvertPointToMortonCode(int64_t x, int64_t y)
{
    int64_t bit = 1;
    int64_t mortonCode = 0;
    if (y < 0)
    {
        y += 0x7FFFFFFF;
    }
    y <<= 1;
    for (int32_t i = 0; i < 32; i++)
    {
        mortonCode |= (x & bit);
        x <<= 1;
        bit <<= 1;
        mortonCode |= (y & bit);
        y <<= 1;
        bit <<= 1;
    }
    return (uint32_t)mortonCode;
}
/**
* mesh is also the name of grid
* @param[in] level   the level id 0 ~ 13.
* @param[in] x   longitude in degree.
* @param[in] y   latitude in degree.
* @param[out] tileId   the morton code and level id, you can also use (meshId << 32 | levelId).
*/
void getTileId(uint8_t levelId, double x, double y, TileId &tileId)
{
    int64_t x = (int64_t)(x * 4294967296 / 360);
    int64_t y = (int64_t)(y * 4294967296 / 360);
    int32_t col = 0, row = 0;
    ConvertXYToRowCol(x, y, levelId, col, row);
    tileId.meshId = ConvertPointToMortonCode(col, row);
    tileId.levelId = level;
}

也可以根据矩形范围计算覆盖的格网,即计算出左上右下所在格网的行列号,根据行列号得到所有的Morton码

总结

结合NDS标准的文档说明,理解格网划分的设计,计算格网ID并不难。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我理解你的要求了。以下是一个用Java编写的函数,根据经纬度坐标计算NDS标准下的格网ID: ```java import java.util.HashMap; import java.util.Map; public class GridIDCalculator { private static final double EARTH_RADIUS = 6371000; // 地球半径,单位:米 // 源坐标系 private static final String SOURCE_COORDINATE_SYSTEM = "WGS84"; // 格子层级 private static final int MAX_LEVEL = 12; // 格网ID计算函数 public static String getGridID(String coordinateSystem, int level, double longitude, double latitude) { if (!coordinateSystem.equals(SOURCE_COORDINATE_SYSTEM) || level > MAX_LEVEL) { return null; } // 计算格子大小 double gridSize = 360.0 / (Math.pow(2, level) * 2); // 计算所在格子的行列号 int col = (int) ((longitude + 180) / gridSize); int row = (int) ((latitude + 90) / gridSize); // 构造格网ID StringBuilder gridID = new StringBuilder(); gridID.append(level).append('-'); gridID.append(row).append('-'); gridID.append(col); return gridID.toString(); } public static void main(String[] args) { // 示例:计算格网ID String gridID = getGridID("WGS84", 10, 116.3975, 39.9085); System.out.println("Grid ID: " + gridID); } } ``` 这个函数接受四个参数:`coordinateSystem`(源坐标系,此处固定为"WGS84"),`level`(格子层级,最大为12),`longitude`(经度),`latitude`(纬度)。它会根据输入的参数计算出对应的NDS标准下的格网ID,并返回结果。 请注意,此处只提供了一个简单的实现示例,实际应用中可能需要考虑更多的坐标系转换和误差处理等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值