Created
April 15, 2019 07:36
-
-
Save theKashey/8f69b8c682a1e7ba8b87c7bbfc5f6948 to your computer and use it in GitHub Desktop.
osme geometry encoder
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var codingCoefficient = 1000000, | |
base64 = require('./ybase64.js'); // this is just atob | |
function getShiftsPoint (path, codingCoefficient) { | |
var res = []; | |
for (var i = 0, l = path.length, prev = [0, 0]; i < l; i++) { | |
res.push([ | |
Math.round((path[i][0] - prev[0]) * codingCoefficient), | |
Math.round((path[i][1] - prev[1]) * codingCoefficient) | |
]); | |
prev = path[i]; | |
} | |
return res; | |
} | |
function encodeNbytes (x, N) { | |
N = N || 4; | |
var chr = []; | |
for (var i = 0; i < N; i++) { | |
chr[i] = x & 0x000000ff; | |
x = x >> 8; | |
} | |
return chr; | |
} | |
function decodeNbytes (x, N) { | |
var point = 0; | |
N = N || 4; | |
for (var i = 0; i < N; ++i) { | |
point |= (x.charCodeAt(i) << (i * 8)); | |
} | |
return point; | |
} | |
function mergeBits (a, b, N) { | |
var r = 0; | |
for (var i = 0; i < N; ++i) { | |
r |= ((a >> i) & 1 | ((b >> i) & 1) << 1) << (i * 2); | |
} | |
return r; | |
} | |
function revjoinBits (a, b, N) { | |
var r = a | 0; | |
for (var i = 0; i < N; ++i) { | |
r |= ((b >> (N - i)) & 1) << (N + i * 2); | |
} | |
return r; | |
} | |
function howManyBits (a) { | |
if (a < Math.pow(2, 8))return 1; | |
if (a < Math.pow(2, 16))return 2; | |
if (a < Math.pow(2, 24))return 3; | |
if (a < Math.pow(2, 32))return 4; | |
} | |
function deltacode (to, values) { | |
// console.log(values);sdf(); | |
var max = 0, st = values[0], deltas = [], delta, deltaSt = {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 8: 0}; | |
for (var i = 1, l = values.length; i < l; ++i) { | |
delta = values[i - 1] - values[i]; | |
deltaSt[howManyBits(Math.abs(delta))]++; | |
// console.log('d',delta); | |
deltas.push(delta); | |
max = Math.max(max, Math.abs(delta)); | |
} | |
console.log('max delta', max, values.length, deltaSt); | |
var nb = 3; | |
{ | |
for (var i = 1, l = values.length; i < l; ++i) { | |
to.push.apply(to, encodeNbytes(deltas[i], nb)); | |
} | |
} | |
} | |
function encodePath (path, codingCoefficient) { | |
var shifts = getShiftsPoint(path, codingCoefficient), | |
result = []; | |
result = result.concat( | |
encodeNbytes(shifts[0][0]), | |
encodeNbytes(shifts[0][1]) | |
); | |
for (var i = 1, l = shifts.length; i < l; i++) { | |
result.push.apply(result, encodeNbytes(shifts[i][0])); | |
result.push.apply(result, encodeNbytes(shifts[i][1])); | |
} | |
return base64.to(result); | |
} | |
function getBounds (path) { | |
var min = path[0].slice(0), | |
max = path[0].slice(0); | |
for (var i = 1, l = path.length; i < l; i++) { | |
min[0] = Math.min(min[0], path[i][0]); | |
min[1] = Math.min(min[1], path[i][1]); | |
max[0] = Math.max(max[0], path[i][0]); | |
max[1] = Math.max(max[1], path[i][1]); | |
} | |
return [min, max]; | |
} | |
function encodeRectPath (path, sizeFactor) { | |
sizeFactor = sizeFactor || 0xFFFF; | |
var bounds = getBounds(path), | |
dim = [bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[0][1]], | |
result = [], | |
fraction = 2, | |
fx = sizeFactor / dim[0], | |
fy = sizeFactor / dim[1]; | |
result = result.concat( | |
encodeNbytes(codingCoefficient * bounds[0][0], 4), | |
encodeNbytes(codingCoefficient * bounds[0][1], 4), | |
encodeNbytes(codingCoefficient * bounds[1][0], 4), | |
encodeNbytes(codingCoefficient * bounds[1][1], 4) | |
); | |
var lastpoint = []; | |
for (var i = 0, l = path.length; i < l; i++) { | |
var point = [ | |
Math.round((path[i][0] - bounds[0][0]) * fx), | |
Math.round((path[i][1] - bounds[0][1]) * fy) | |
]; | |
if (lastpoint[0] != point[0] || lastpoint[1] != point[1]) { | |
lastpoint = point; | |
result.push.apply(result, encodeNbytes(point[0], fraction)); | |
result.push.apply(result, encodeNbytes(point[1], fraction)); | |
} | |
} | |
return base64.to(result); | |
} | |
function encodeRect32Path (path, sizeFactor) { | |
sizeFactor = 0xFFFF; | |
var bounds = getBounds(path), | |
dim = [bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[0][1]], | |
result = [], | |
fraction = 4, | |
fx = sizeFactor / dim[0], | |
fy = sizeFactor / dim[1]; | |
result = result.concat( | |
encodeNbytes(codingCoefficient * bounds[0][0], 4), | |
encodeNbytes(codingCoefficient * bounds[0][1], 4), | |
encodeNbytes(codingCoefficient * bounds[1][0], 4), | |
encodeNbytes(codingCoefficient * bounds[1][1], 4) | |
); | |
var lastpoint = [], | |
values = []; | |
for (var i = 0, l = path.length; i < l; i++) { | |
var point = [ | |
Math.round((path[i][0] - bounds[0][0]) * fx), | |
Math.round((path[i][1] - bounds[0][1]) * fy) | |
]; | |
if (lastpoint[0] != point[0] || lastpoint[1] != point[1]) { | |
lastpoint = point; | |
var dpoint = mergeBits(point[0], point[1], 16); | |
result.push.apply(result, encodeNbytes(dpoint, fraction)); | |
} | |
} | |
return base64.to(result); | |
} | |
function encodeRectZPath (path, sizeFactor) { | |
var z = require('zcode.js'); | |
var h = require('hilbertCode.js'); | |
sizeFactor = 0xFFFF; | |
var bounds = getBounds(path), | |
dim = [bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[0][1]], | |
result = [], | |
fraction = 3, | |
fx = sizeFactor / dim[0], | |
fy = sizeFactor / dim[1]; | |
result = result.concat( | |
encodeNbytes(codingCoefficient * bounds[0][0], 4), | |
encodeNbytes(codingCoefficient * bounds[0][1], 4), | |
encodeNbytes(codingCoefficient * bounds[1][0], 4), | |
encodeNbytes(codingCoefficient * bounds[1][1], 4) | |
); | |
var r1 = result.slice(0), r2 = result.slice(0), cx = 0; | |
var lastpoint = [], | |
values = []; | |
for (var i = 0, l = path.length; i < l; i++) { | |
var point = [ | |
Math.round((path[i][0] - bounds[0][0]) * fx), | |
Math.round((path[i][1] - bounds[0][1]) * fy) | |
]; | |
//var cz1 = z.z(point, [[0, 0], [0xFFFF, 0xFFFF]], 16).code; | |
// console.log(cz1,point); | |
//cz1 = cz1.code; | |
var cz1 = h.toCode([point[0] / sizeFactor, point[1] / sizeFactor]); | |
//console.log(cz1); | |
// dfg(); | |
//var cz2 = z.z(point, [[0, 0xFFFF], [0, 0xFFFF]], 8).code; | |
if (cz1 != z) { | |
if (cx++ % 2 && 0) { | |
r1.push(revjoinBits(cz2, lastpoint, 8)); | |
lastpoint = cz2; | |
} else { | |
lastpoint = cz1; | |
//values.push(cz1); | |
/* | |
var t = encodeNbytes(cz1, 8); | |
console.log(cz1,4,t); | |
var d = decodeNbytes(t, 4); | |
if (t != d) { | |
console.log(t, '!=', d, cz1); | |
}*/ | |
r1.push.apply(r1, encodeNbytes(cz1, 4)); | |
} | |
//r2.push(cz2); | |
} | |
} | |
//deltacode(r1, values); | |
return base64.to(r1);//[base64.to(r1), base64.to(r2)]; | |
} | |
function decodeRectPath (encodedCoordinates) { | |
function decodeNbytes (x, N) { | |
var point = 0; | |
for (var i = 0; i < N; ++i) { | |
point |= (x.charCodeAt(i) << (i * 8)); | |
} | |
return point; | |
} | |
var byteVector = base64.from(encodedCoordinates), | |
byteVectorLength = byteVector.length, | |
codingCoefficient = 1000000, | |
bounds = [ | |
[decodeNbytes(byteVector.substr(0, 4), 4) / codingCoefficient, decodeNbytes(byteVector.substr(4, 4), 4) / codingCoefficient], | |
[decodeNbytes(byteVector.substr(8, 4), 4) / codingCoefficient, decodeNbytes(byteVector.substr(12, 4), 4) / codingCoefficient] | |
], | |
dim = [bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[0][1]], | |
result = [], | |
index = 16, | |
fraction = 2, | |
fx = dim[0] / 0xFFFF, | |
fy = dim[1] / 0xFFFF; | |
while (index < byteVectorLength) { | |
var x = byteVector.substr(index, fraction), | |
y = byteVector.substr(index + fraction, fraction), | |
pointx = decodeNbytes(x, fraction), | |
pointy = decodeNbytes(y, fraction); | |
result.push([pointx * fx + bounds[0][0], pointy * fy + bounds[0][1]]); | |
index += fraction * 2; | |
} | |
return result; | |
} | |
function decodePath (encodedCoordinates, codingCoefficient) { | |
var byteVector = base64.from(encodedCoordinates), | |
byteVectorLength = byteVector.length, | |
index = 0, | |
prev = [0, 0], | |
result = []; | |
while (index < byteVectorLength) { | |
var x = byteVector.substr(index, 4), | |
y = byteVector.substr(index + 4, 4), | |
pointx = decodeNbytes(x), | |
pointy = decodeNbytes(y); | |
var vector = [pointx / codingCoefficient, pointy / codingCoefficient], | |
point = [vector[0] + prev[0], vector[1] + prev[1]]; | |
prev = point; | |
result.push(point); | |
index += 8; | |
} | |
return result; | |
}; | |
exports.encodeRect32 = encodeRect32Path; | |
exports.encodeRectZ = encodeRectZPath; | |
exports.encodeRect = encodeRectPath; | |
exports.decodeRect = decodeRectPath; | |
exports.encode = function (path, components) { | |
if (components == 1) { | |
return encodeStrip(path, 1); | |
} else { | |
return encodePath(path, codingCoefficient); | |
} | |
} | |
exports.decode = function (string, components) { | |
if (components == 1) { | |
return decodeStrip(string, 1); | |
} else { | |
return decodePath(string, codingCoefficient); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=", | |
Base64 = { | |
baseString: keyStr, | |
to: function (input) { | |
var inputIsString = typeof input == "string"; | |
if (typeof btoa != "undefined") { | |
if (!inputIsString) { | |
input = String.fromCharCode.apply(String, input); | |
} | |
return btoa(input).replace(/\//g, '_').replace(/\+/g, '-'); | |
} else { | |
var output = [], | |
chr1, chr2, chr3, enc1, enc2, enc3, enc4, | |
i = 0, | |
l = input.length; | |
while (i < l) { | |
if (inputIsString) { | |
chr1 = input.charCodeAt(i++); | |
chr2 = input.charCodeAt(i++); | |
chr3 = input.charCodeAt(i++); | |
} else { | |
chr1 = input[i++]; | |
chr2 = input[i++]; | |
chr3 = input[i++]; | |
} | |
enc1 = chr1 >> 2; | |
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); | |
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); | |
enc4 = chr3 & 63; | |
if (isNaN(chr2)) { | |
enc3 = enc4 = 64; | |
} else if (isNaN(chr3)) { | |
enc4 = 64; | |
} | |
output.push(keyStr.charAt(enc1), keyStr.charAt(enc2), keyStr.charAt(enc3), keyStr.charAt(enc4)); | |
} | |
return output.join(""); | |
} | |
}, | |
from: function (input) { | |
if (typeof atob != "undefined") { | |
return atob(input.replace(/_/g, '/').replace(/-/g, '+')); | |
} else { | |
var output = [], | |
chr1, chr2, chr3, | |
enc1, enc2, enc3, enc4, | |
i = 0, | |
l = (input = input.replace(/[^A-Za-z0-9\-_\=]/g, "")).length; | |
while (i < l) { | |
enc1 = keyStr.indexOf(input.charAt(i++)); | |
enc2 = keyStr.indexOf(input.charAt(i++)); | |
enc3 = keyStr.indexOf(input.charAt(i++)); | |
enc4 = keyStr.indexOf(input.charAt(i++)); | |
chr1 = (enc1 << 2) | (enc2 >> 4); | |
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); | |
chr3 = ((enc3 & 3) << 6) | enc4; | |
output.push(String.fromCharCode(chr1)); | |
if (enc3 != 64) { | |
output.push(String.fromCharCode(chr2)); | |
} | |
if (enc4 != 64) { | |
output.push(String.fromCharCode(chr3)); | |
} | |
} | |
return output.join(""); | |
} | |
} | |
}; | |
exports.to = Base64.to; | |
exports.from = Base64.from; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment