背景
前回考えたZ階数曲線をベースにした地理インデックスの計算をUnityで使えるようにC#で書いてみる。
若干冗長なキャストがありそうだけど、以下コード。
bit_tableが1ビット置きに歯抜け配置に変換するためのテーブル。8ビット分をすべて用意して、4回に分けて32ビット分を処理している。
もし、簡単なビット演算だけでやる方法があったら教えてほしいです。
GeoIndexCalc.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GeoIndexCalc
{
private static ushort[] bit_table = new ushort[]
{
0,1,4,5,16,17,20,21,
64,65,68,69,80,81,84,85,
256,257,260,261,272,273,276,277,
320,321,324,325,336,337,340,341,
1024,1025,1028,1029,1040,1041,1044,1045,
1088,1089,1092,1093,1104,1105,1108,1109,
1280,1281,1284,1285,1296,1297,1300,1301,
1344,1345,1348,1349,1360,1361,1364,1365,
4096,4097,4100,4101,4112,4113,4116,4117,
4160,4161,4164,4165,4176,4177,4180,4181,
4352,4353,4356,4357,4368,4369,4372,4373,
4416,4417,4420,4421,4432,4433,4436,4437,
5120,5121,5124,5125,5136,5137,5140,5141,
5184,5185,5188,5189,5200,5201,5204,5205,
5376,5377,5380,5381,5392,5393,5396,5397,
5440,5441,5444,5445,5456,5457,5460,5461,
16384,16385,16388,16389,16400,16401,16404,16405,
16448,16449,16452,16453,16464,16465,16468,16469,
16640,16641,16644,16645,16656,16657,16660,16661,
16704,16705,16708,16709,16720,16721,16724,16725,
17408,17409,17412,17413,17424,17425,17428,17429,
17472,17473,17476,17477,17488,17489,17492,17493,
17664,17665,17668,17669,17680,17681,17684,17685,
17728,17729,17732,17733,17744,17745,17748,17749,
20480,20481,20484,20485,20496,20497,20500,20501,
20544,20545,20548,20549,20560,20561,20564,20565,
20736,20737,20740,20741,20752,20753,20756,20757,
20800,20801,20804,20805,20816,20817,20820,20821,
21504,21505,21508,21509,21520,21521,21524,21525,
21568,21569,21572,21573,21584,21585,21588,21589,
21760,21761,21764,21765,21776,21777,21780,21781,
21824,21825,21828,21829,21840,21841,21844,21845
};
public static ulong calcIndex(double lat, double lon)
{
uint _lat = (uint)((lat + 90.0) * (double)UInt32.MaxValue / 180.0);
uint _lon = (uint)((lon + 180.0) * (double)UInt32.MaxValue / 360.0);
ulong index = 0;
byte x_byte0 = (byte)(_lon & 0xFF);
byte x_byte1 = (byte)((_lon >> 8) & 0xFF);
byte x_byte2 = (byte)((_lon >> 16) & 0xFF);
byte x_byte3 = (byte)((_lon >> 24) & 0xFF);
index |= (ulong)bit_table[x_byte3] << 49;
index |= (ulong)bit_table[x_byte2] << 33;
index |= (ulong)bit_table[x_byte1] << 17;
index |= (ulong)bit_table[x_byte0] << 1;
byte y_byte0 = (byte)(_lat & 0xFF);
byte y_byte1 = (byte)((_lat >> 8) & 0xFF);
byte y_byte2 = (byte)((_lat >> 16) & 0xFF);
byte y_byte3 = (byte)((_lat >> 24) & 0xFF);
index |= (ulong)bit_table[y_byte3] << 48;
index |= (ulong)bit_table[y_byte2] << 32;
index |= (ulong)bit_table[y_byte1] << 16;
index |= (ulong)bit_table[y_byte0];
return index;
}
}