Geohash-16:怎么样

时间:2018-03-06 17:39:52

标签: javascript character-encoding binary base geohashing

情况:

我有使用geohash系统创建base-32的JavaScript代码。

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模块(source code)获取的。

问题:

我不擅长数字系统二进制数据等。我不知道如何将编码改为base-16系统('0123456789abcdef')。 如果有人改变它或者只是指出我需要改变什么,我会很高兴。感谢。

1 个答案:

答案 0 :(得分:1)

所以我认为你只需改变三件事:

  • 字母表定义(代码段中的BASE32_CODES),改为使用基本的16个字符集。
  • 写字符前要收集的位数(使用4而不是5)
  • 要输出的总字符数(因为每个字符的信息较少,您需要更多的字符才能传输相同的数据)。

因为我们正在从5 - >开始每个字符4位,我们需要额外的字符才能达到相同的精度(5bits / char * 9chars = 45bits,所以我们需要在16位中至少12个字符才能达到相同的精度(4bits / 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]