NDS座標系におけるタイル番号の計算方法

NDSはWGS84座標系(1984年世界測地系)を使用しています。これは一般的に知られる経度・緯度の座標系です。特定の位置を指定する際には、その地点の経度と緯度を指定することで、正確な位置を一意に特定できます。

NDSはEGM96(1996年地球重力モデル)を使用して高度情報を表現します。EGM96で表される高度情報は標高を良好に近似しており、WGS84の高度情報よりも正確です。

経度は32ビットintで符号化され、[-180, 180]の範囲を表現できます。緯度は31ビットintで符号化され、[-90, 90]の範囲を表現できます。

例:エッフェル塔の計算(Eiffel Tower 2.2945° 48.858222°)

lon = 2.2945 lon_to_int32 = pow(2, 31) * 2.2945 / 180 = 2147483648 * 2.2945 / 180 = 27374451.279644444444444444444444 = 27374451(切り捨てfloorを使用) = 0x1a1b373(16進数) = ‭0001101000011011001101110011‬(2進数)

lat = 48.858222 lat_to_int32 = pow(2, 30) * 48.858222 / 90 = 1073741824 * 48.858222 / 90 = 582901293.41863253333333333333333 = 582901293(切り捨てfloorを使用) = 0x22be5e2d(16進数) = ‭00100010101111100101111000101101‬(2進数)

モートン符号(morton code)を使用して符号化します x = x31x30...x1x0 y = y30...y1y0 c = x31y30x30...y1x1y0x0 全長63ビット(32+31)

x = 0x1a1b373 1 1 0 1 0 0 0 0 1 1 0 1 1 0 0 1 1 0 1 1 1 0 0 1 1 y = 0x22be5e2d 1 0 0 0 1 0 1 0 1 1 1 1 1 0 0 1 0 1 1 1 1 0 0 0 1 0 1 1 0 1 c = 0x809cea967ad1da7 100000001001110011101010100101100111101011010001110110100111

x = 0x1a1b373                    1 1 0 1 0 0 0 0 1 1 0 1 1 0 0 1 1 0 1 1 1 0 0 1 1
y = 0x22be5e2d        1 0 0 0 1 0 1 0 1 1 1 1 1 0 0 1 0 1 1 1 1 0 0 0 1 0 1 1 0 1 
c = 0x809cea967ad1da7 100000001001110011101010100101100111101011010001110110100111

63ビットに整列 000100000001001110011101010100101100111101011010001110110100111

したがって、この点のLevel10のタイル番号は Level10 = c.left(2n+1) = c.left(2*10+1) = c.left(21) = 0 0010 0000 0010 0111 0011 = 0x‭20273‬ = ‭131699‬

したがって、この点のLevel13のタイル番号は Level13 = c.left(2n+1) = c.left(2*13+1) = c.left(27) = 000 1000 0000 1001 1100 1110 1010 = 0x‭‭809CEA‬ = ‭8428778‬

 1 struct CoordinateConverter {
 2     double   longitude;
 3     double   latitude;
 4     int32_t  encodedLon;
 5     int32_t  encodedLat;
 6     uint64_t mortonCode;
 7 
 8     CoordinateConverter(double lon, double lat) : longitude(lon), latitude(lat), encodedLon(0), encodedLat(0), mortonCode(0) {
 9         encodedLon   = convertLongitude(lon);
10         encodedLat   = convertLatitude(lat);
11         mortonCode = calculateMortonCode(encodedLon, encodedLat);
12 
13         printf("座標:[%10.6lf,%10.6lf], NDS:[%12d,%12d] モートン:[%24lu]\n", longitude, latitude, encodedLon, encodedLat, mortonCode);
14     }
15 
16     int32_t convertLongitude(double lon) {
17         bool isPositive = true;
18         if (lon < 0) {
19             isPositive = false;
20         }
21         auto temp = pow(2, 31) * lon / 180.0;
22         return isPositive ? std::floor(temp) : std::ceil(temp);
23     }
24 
25     int32_t convertLatitude(double lat) {
26         bool isPositive = true;
27         if (lat < 0) {
28             isPositive = false;
29             lat += 180.0;
30         }
31         auto temp = pow(2, 30) * lat / 90.0;
32         return isPositive ? std::floor(temp) : std::ceil(temp);
33     }
34 
35     uint64_t calculateMortonCode(int32_t lonValue, int32_t latValue) {
36         uint64_t mortonResult = 0;
37         for (int i = 0; i < 32; i++) {
38             uint64_t temp64 = 0;
39             temp64          = (lonValue >> i) & 0x1;
40             temp64 |= ((latValue >> i) & 0x1) << 1;
41             mortonResult |= (temp64 << 2 * i);
42         }
43 
44         return mortonResult;
45     }
46 };

タグ: NDS WGS84 モートン符号 座標変換 タイル番号

5月19日 11:08 投稿