diff --git a/misc/coord64.js b/misc/coord64.js new file mode 100644 index 00000000..880f509e --- /dev/null +++ b/misc/coord64.js @@ -0,0 +1,87 @@ +/* + * Coordinate ID generator: + * Takes a set of 3d coordinates (x, y, z), truncates to 2dp and then + * generates a base64-like(*) representation that can be used as an id + * for the object. + * + * The actual encoding is not base64, since base64 contains characters + * that present a problem when used, e.g, in URIs. I replaced the '+' + * and '/' characters with '_' and '.' respectively. + * + * Example usage: + * coord_to_id64(51.5625, 32.1875, -27.125) + * Generates: + * "1gA:Oi:-Go" + * + * A reversing function is also provided. + * + * Original Author: Oliver "kfsone" Smith + * Released under the "use it with attribution" license. + */ + +var alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_."; +var precision = 100.; + +function coord_to_d64(coord) { + var i = parseInt(Math.abs(coord * precision)); + + var digits = "" + do { + digits = alphabet[i & 63] + digits; + i >>= 6; // shift right by a digit (>>= 6) + } while (i > 0); + + return (coord < 0) ? ("-"+digits) : (digits); +} + +function d64_to_coord(d64) { + var divisor = precision; + var pos = 0; + if (d64[0] == '-') { + divisor = -divisor; + pos++; + } + + var number = 0; + for ( ; pos < d64.length ; ++pos ) { + var value = alphabet.indexOf(d64[pos]); + if (value < 0) + throw "Invalid d64 value: " + d64; + number = (number * 64) + value; + } + + return number / divisor; +} + +function pos_to_id64(x, y, z) { + return coord_to_d64(x) + ':' + coord_to_d64(y) + ':' + coord_to_d64(z); +} + +function id64_to_pos(id64) { + d64s = id64.split(':'); + return [ d64_to_coord(d64s[0]), + d64_to_coord(d64s[1]), + d64_to_coord(d64s[2]) + ]; +} + +/* + * Test cases + * + +function test_conv(testPos) { + id64 = pos_to_id64(testPos[0], testPos[1], testPos[2]); + document.write("id64 [", testPos.join(','), "] = ", id64, "\n") + pos = id64_to_pos(id64); + document.write("pos of ", id64, " = [", pos.join(','), "]\n"); +} + +var test1 = [ 51.5625,32.1875,-27.125 ]; +var test2 = [ -154.65625,40.34375,-82.78125 ]; + +test_conv(test1); +test_conv(test1); +test_conv(test2); + +*/ + diff --git a/misc/coord64.py b/misc/coord64.py new file mode 100644 index 00000000..80c10e71 --- /dev/null +++ b/misc/coord64.py @@ -0,0 +1,82 @@ +# Coordinate ID generator: +# Takes a set of 3d coordinates (x, y, z), truncates to 2dp and then +# generates a base64-like(*) representation that can be used as an id +# for the object. +# +# The actual encoding is not base64, since base64 contains characters +# that present a problem when used, e.g, in URIs. I replaced the '+' +# and '/' characters with '_' and '.' respectively. +# +# Example usage: +# coord_to_id64(51.5625, 32.1875, -27.125) +# Generates: +# "1gA:Oi:-Go" +# +# A reversing function is also provided. +# +# Original Author: Oliver "kfsone" Smith +# Released under the "use it with attribution" license. + +from __future__ import print_function, division +import string + +alphabet = string.digits + string.ascii_lowercase + string.ascii_uppercase + '_.' +precision = 100. + +def coord_to_d64(coord): + i = int(abs(coord * precision)) + + digits = "" + while True: + digits = alphabet[i & 63] + digits + i >>= 6 # divides by 64, or one digit + if i == 0: + break + + sign = '-' if coord < 0 else '' + return sign + digits + + +def d64_to_coord(d64): + divisor, digits = precision, d64 + if d64.startswith('-'): + divisor = -divisor + digits = digits[1:] + + number = 0 + for digit in digits: + value = alphabet.find(digit) + if value < 0: + raise ValueError("Invalid d64 value: {}".format(value)) + number = (number * 64) + value + + return number / divisor + + +def pos_to_id64(x, y, z): + return coord_to_d64(x) + ':' + coord_to_d64(y) + ':' + coord_to_d64(z) + + +def id64_to_pos(id64): + (x64, y64, z64) = id64.split(':') + return (d64_to_coord(x64), d64_to_coord(y64), d64_to_coord(z64)) + + +if __name__ == "__main__": + test1 = ( 51.5625,32.1875,-27.125 ) + test2 = ( -154.65625,40.34375,-82.78125 ) + + id64 = pos_to_id64(test1[0], test1[1], test1[2]) + print("id64 of {} = {}".format(test1, id64)) + pos = id64_to_pos(id64) + print("pos of {} = {}".format(id64, pos)) + + id64 = pos_to_id64(test1[0], test1[1], test1[2]) + print("id64 of {} = {}".format(test1, id64)) + pos = id64_to_pos(id64) + print("pos of {} = {}".format(id64, pos)) + + id64 = pos_to_id64(test2[0], test2[1], test2[2]) + print("id64 of {} = {}".format(test2, id64)) + pos = id64_to_pos(id64) + print("pos of {} = {}".format(id64, pos))