-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCoordEncoder.js
151 lines (135 loc) · 4.57 KB
/
CoordEncoder.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//eCharts的GeoJson地理坐标压缩和解压zigzag算法
//https://github.com/apache/echarts
const fs = require("fs");
try {
//获取输入和输出文件名
let inputFile,
outputFile;
if (process.argv.length == 4) {
inputFile = process.argv[2];
outputFile = process.argv[3];
fs.readFile(inputFile, "utf8", (err, data) => {
const res = encodeGeo(JSON.parse(data));
fs.writeFileSync(outputFile, JSON.stringify(res));
});
console.log("Successfully encode coordinators in " + inputFile + " and save to:" + outputFile);
return true;
} else {
throw new Error("Please provide parameter of inputFile and outputFile for coordinators encoding by zigzag algorithm.");
}
} catch (err) {
console.log(err);
return false;
}
// 压缩算法
function encodePolygon(coordinate, encodeOffsets) {
var result = "";
var prevX = quantize(coordinate[0][0]);
var prevY = quantize(coordinate[0][1]);
// Store the origin offset
encodeOffsets[0] = prevX;
encodeOffsets[1] = prevY;
for (var i = 0; i < coordinate.length; i++) {
var point = coordinate[i];
result += encode(point[0], prevX);
result += encode(point[1], prevY);
prevX = quantize(point[0]);
prevY = quantize(point[1]);
}
return result;
}
function encode(val, prev) {
// Quantization
val = quantize(val);
val = val - prev;
if (((val << 1) ^ (val >> 15)) + 64 === 8232) {
//WTF, 8232 will get syntax error in js code
val--;
}
// ZigZag
val = (val << 1) ^ (val >> 15);
// add offset and get unicode
return String.fromCharCode(val + 64);
}
function quantize(val) {
return Math.ceil(val * 1024);
}
function encodeGeo(geo) {
// 压缩标识
geo.UTF8Encoding = true;
geo.UTF8Scale = 1024;
for (let f_i = 0; f_i < geo.features.length; f_i++) {
var geometry = geo.features[f_i].geometry;
if (geometry.type === "Polygon") {
var coordinates = geometry.coordinates;
geometry.encodeOffsets = Array(coordinates.length);
for (let c = 0; c < coordinates.length; c++) {
var offset = Array(2);
var codeStr = encodePolygon(coordinates[c], offset);
coordinates[c] = codeStr;
geometry.encodeOffsets[c] = offset;
}
} else if (geometry.type === "MultiPolygon") {
var coordinates = geometry.coordinates;
geometry.encodeOffsets = Array(coordinates.length);
for (let c = 0; c < coordinates.length; c++) {
var coordinate = coordinates[c];
geometry.encodeOffsets[c] = Array(coordinate.length);
for (let c2 = 0; c2 < coordinate.length; c2++) {
var offset = Array(2);
var codeStr = encodePolygon(coordinate[c2], offset);
coordinate[c2] = codeStr;
geometry.encodeOffsets[c][c2] = offset;
}
}
}
}
return geo;
}
//解压算法
function decode(json) {
if (!json.UTF8Encoding) {
return json;
}
var features = json.features;
for (var f = 0; f < features.length; f++) {
var feature = features[f];
var geometry = feature.geometry;
var coordinates = geometry.coordinates;
var encodeOffsets = geometry.encodeOffsets;
for (var c = 0; c < coordinates.length; c++) {
var coordinate = coordinates[c];
if (geometry.type === "Polygon") {
coordinates[c] = decodePolygon(coordinate, encodeOffsets[c]);
} else if (geometry.type === "MultiPolygon") {
for (var c2 = 0; c2 < coordinate.length; c2++) {
var polygon = coordinate[c2];
coordinate[c2] = decodePolygon(polygon, encodeOffsets[c][c2]);
}
}
}
}
// Has been decoded
json.UTF8Encoding = false;
return json;
}
function decodePolygon(coordinate, encodeOffsets) {
var result = [];
var prevX = encodeOffsets[0];
var prevY = encodeOffsets[1];
for (var i = 0; i < coordinate.length; i += 2) {
var x = coordinate.charCodeAt(i) - 64;
var y = coordinate.charCodeAt(i + 1) - 64;
// ZigZag decoding
x = (x >> 1) ^ - (x & 1);
y = (y >> 1) ^ - (y & 1);
// Delta decoding
x += prevX;
y += prevY;
prevX = x;
prevY = y;
// Dequantize
result.push([x / 1024, y / 1024]);
}
return result;
}