Геохаш-16: как
Ситуация:
У меня есть код JavaScript, который создает геохэш с системой base-32.
var BASE32_CODES = "0123456789bcdefghjkmnpqrstuvwxyz";
var BASE32_CODES_DICT = {};
for (var i = 0; i < BASE32_CODES.length; i++) {
BASE32_CODES_DICT[BASE32_CODES.charAt(i)] = i;
}
var ENCODE_AUTO = 'auto';
var SIGFIG_HASH_LENGTH = [0, 5, 7, 8, 11, 12, 13, 15, 16, 17, 18];
var encode = function (latitude, longitude, numberOfChars) {
if (numberOfChars === ENCODE_AUTO) {
if (typeof(latitude) === 'number' || typeof(longitude) === 'number') {
throw new Error('string notation required for auto precision.');
}
var decSigFigsLat = latitude.split('.')[1].length;
var decSigFigsLong = longitude.split('.')[1].length;
var numberOfSigFigs = Math.max(decSigFigsLat, decSigFigsLong);
numberOfChars = SIGFIG_HASH_LENGTH[numberOfSigFigs];
} else if (numberOfChars === undefined) {
numberOfChars = 9;
}
var chars = [],
bits = 0,
bitsTotal = 0,
hash_value = 0,
maxLat = 90,
minLat = -90,
maxLon = 180,
minLon = -180,
mid;
while (chars.length < numberOfChars) {
if (bitsTotal % 2 === 0) {
mid = (maxLon + minLon) / 2;
if (longitude > mid) {
hash_value = (hash_value << 1) + 1;
minLon = mid;
} else {
hash_value = (hash_value << 1) + 0;
maxLon = mid;
}
} else {
mid = (maxLat + minLat) / 2;
if (latitude > mid) {
hash_value = (hash_value << 1) + 1;
minLat = mid;
} else {
hash_value = (hash_value << 1) + 0;
maxLat = mid;
}
}
bits++;
bitsTotal++;
if (bits === 5) {
var code = BASE32_CODES[hash_value];
chars.push(code);
bits = 0;
hash_value = 0;
}
}
return chars.join('');
};
На самом деле, я взял его из модуля ngeohash npm ( исходный код).
Проблема:
Я плохо разбираюсь в двоичных данных систем счисления и т. Д. Я не знаю, как изменить кодировку для системы base-16 ('0123456789abcdef'). Я буду счастлив, если кто-то изменит это или просто укажет мне, что мне нужно изменить. Благодарю.
1 ответ
Поэтому я думаю, что вам нужно изменить только три вещи:
- Определение алфавита (
BASE32_CODES
в вашем фрагменте), чтобы вместо него были установлены базовые 16 символов. - Количество бит, которые нужно собрать перед написанием символа (используйте 4 вместо 5)
- Общее количество символов для вывода (поскольку каждый символ несет меньше информации, вам потребуется больше из них для переноса одних и тех же данных).
Поскольку мы переходим от 5 -> 4 бит на символ, нам потребуются дополнительные символы для достижения одинаковой точности (5 бит / символ * 9 символов = 45 бит, поэтому нам нужно не менее 12 символов в базе 16 для одинаковой точности (4 бита /char * 12chars = 48bits, поэтому мы получаем некоторую дополнительную точность с этим количеством символов)
Таким образом, ваш фрагмент станет:
var BASE16_CODES = "0123456789abcdef"; // <-- changed this
var BASE16_CODES_DICT = {};
for (var i = 0; i < BASE16_CODES.length; i++) {
BASE16_CODES_DICT[BASE16_CODES.charAt(i)] = i;
}
var ENCODE_AUTO = 'auto';
var SIGFIG_HASH_LENGTH = [0, 5, 7, 8, 11, 12, 13, 15, 16, 17, 18];
var encode = function (latitude, longitude, numberOfChars) {
if (numberOfChars === ENCODE_AUTO) {
if (typeof(latitude) === 'number' || typeof(longitude) === 'number') {
throw new Error('string notation required for auto precision.');
}
var decSigFigsLat = latitude.split('.')[1].length;
var decSigFigsLong = longitude.split('.')[1].length;
var numberOfSigFigs = Math.max(decSigFigsLat, decSigFigsLong);
numberOfChars = SIGFIG_HASH_LENGTH[numberOfSigFigs];
} else if (numberOfChars === undefined) {
numberOfChars = 12; // <-- and this
}
var chars = [],
bits = 0,
bitsTotal = 0,
hash_value = 0,
maxLat = 90,
minLat = -90,
maxLon = 180,
minLon = -180,
mid;
while (chars.length < numberOfChars) {
if (bitsTotal % 2 === 0) {
mid = (maxLon + minLon) / 2;
if (longitude > mid) {
hash_value = (hash_value << 1) + 1;
minLon = mid;
} else {
hash_value = (hash_value << 1) + 0;
maxLon = mid;
}
} else {
mid = (maxLat + minLat) / 2;
if (latitude > mid) {
hash_value = (hash_value << 1) + 1;
minLat = mid;
} else {
hash_value = (hash_value << 1) + 0;
maxLat = mid;
}
}
bits++;
bitsTotal++;
if (bits === 4) { // <-- and finally this
var code = BASE16_CODES[hash_value];
chars.push(code);
bits = 0;
hash_value = 0;
}
}
return chars.join('');
};
console.log(encode(...[40.676843, -73.935769]))
РЕДАКТИРОВАТЬ: если подумать, если вы используете ENCODE_AUTO
Функция этой функции, вам нужно увеличить значения в SIGFIG_HASH_LENGTH
также массив (по той же причине, что и раньше, для той же или большей точности требуется больше символов). Так что должно получиться так:
var SIGFIG_HASH_LENGTH = [0, 7, 9, 10, 14, 15, 17, 19, 20, 22, 23]