Avoid integer overflow when computing shortcodes
Although javascript's numbers are double precision floating point number which support 52 bits of precision the bitwise operations are only guaranteed to work at 32 bits of precision so we need to avoid relying on them doing more than that.
This commit is contained in:
parent
616e9ce7b9
commit
42ef10ba80
1 changed files with 24 additions and 12 deletions
|
@ -254,23 +254,35 @@ function i18n(string, keys) {
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called to interlace the bits in x and y, making a Morton code.
|
||||||
|
*/
|
||||||
|
function interlace(x, y) {
|
||||||
|
x = (x | (x << 8)) & 0x00ff00ff;
|
||||||
|
x = (x | (x << 4)) & 0x0f0f0f0f;
|
||||||
|
x = (x | (x << 2)) & 0x33333333;
|
||||||
|
x = (x | (x << 1)) & 0x55555555;
|
||||||
|
|
||||||
|
y = (y | (y << 8)) & 0x00ff00ff;
|
||||||
|
y = (y | (y << 4)) & 0x0f0f0f0f;
|
||||||
|
y = (y | (y << 2)) & 0x33333333;
|
||||||
|
y = (y | (y << 1)) & 0x55555555;
|
||||||
|
|
||||||
|
return (x << 1) | y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called to create a short code for the short link.
|
||||||
|
*/
|
||||||
function makeShortCode(lat, lon, zoom) {
|
function makeShortCode(lat, lon, zoom) {
|
||||||
char_array = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@";
|
char_array = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@";
|
||||||
var x = Math.round((lon + 180.0) * ((1 << 30) / 90.0));
|
var x = Math.round((lon + 180.0) * ((1 << 30) / 90.0));
|
||||||
var y = Math.round((lat + 90.0) * ((1 << 30) / 45.0));
|
var y = Math.round((lat + 90.0) * ((1 << 30) / 45.0));
|
||||||
// hack around the fact that JS apparently only allows 53-bit integers?!?
|
// JavaScript only has to keep 32 bits of bitwise operators, so this has to be
|
||||||
// note that, although this reduces the accuracy of the process, it's fine for
|
// done in two parts. each of the parts c1/c2 has 30 bits of the total in it
|
||||||
// z18 so we don't need to care for now.
|
// and drops the last 4 bits of the full 64 bit Morton code.
|
||||||
var c1 = 0, c2 = 0;
|
|
||||||
for (var i = 31; i > 16; --i) {
|
|
||||||
c1 = (c1 << 1) | ((x >> i) & 1);
|
|
||||||
c1 = (c1 << 1) | ((y >> i) & 1);
|
|
||||||
}
|
|
||||||
for (var i = 16; i > 1; --i) {
|
|
||||||
c2 = (c2 << 1) | ((x >> i) & 1);
|
|
||||||
c2 = (c2 << 1) | ((y >> i) & 1);
|
|
||||||
}
|
|
||||||
var str = "";
|
var str = "";
|
||||||
|
var c1 = interlace(x >>> 17, y >>> 17), c2 = interlace((x >>> 2) & 0x7fff, (y >>> 2) & 0x7fff);
|
||||||
for (var i = 0; i < Math.ceil((zoom + 8) / 3.0) && i < 5; ++i) {
|
for (var i = 0; i < Math.ceil((zoom + 8) / 3.0) && i < 5; ++i) {
|
||||||
digit = (c1 >> (24 - 6 * i)) & 0x3f;
|
digit = (c1 >> (24 - 6 * i)) & 0x3f;
|
||||||
str += char_array.charAt(digit);
|
str += char_array.charAt(digit);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue