summaryrefslogtreecommitdiffhomepage
path: root/gui/scripts/prepare-rtree.ts
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2019-04-09 15:42:36 +0200
committerAndrej Mihajlov <and@mullvad.net>2019-04-09 15:42:36 +0200
commitb427aa1adca8fcfeca7f777499f0b4e1c84e3c6e (patch)
treeb096c6eb2a2bf3885436910894249452ccb1d813 /gui/scripts/prepare-rtree.ts
parent88031a653167df93396433fcf53a1422c2f995fd (diff)
parent6405e1eebbe12313bed10f3f8bd1a0f051e83d24 (diff)
downloadmullvadvpn-b427aa1adca8fcfeca7f777499f0b4e1c84e3c6e.tar.xz
mullvadvpn-b427aa1adca8fcfeca7f777499f0b4e1c84e3c6e.zip
Merge branch 'multi-catalogue'
Diffstat (limited to 'gui/scripts/prepare-rtree.ts')
-rw-r--r--gui/scripts/prepare-rtree.ts104
1 files changed, 104 insertions, 0 deletions
diff --git a/gui/scripts/prepare-rtree.ts b/gui/scripts/prepare-rtree.ts
new file mode 100644
index 0000000000..3f2519d0c0
--- /dev/null
+++ b/gui/scripts/prepare-rtree.ts
@@ -0,0 +1,104 @@
+//
+// Script that generates r-trees for geo data.
+// run with `npx babel-node geo-data/prepare-rtree.js`
+//
+
+import * as fs from 'fs';
+import * as path from 'path';
+import { Topology, GeometryCollection } from 'topojson-specification';
+import { GeoJSON } from 'geojson';
+import rbush from 'rbush';
+
+interface GeometryTopologyObjects {
+ [key: string]: any;
+ geometry: GeometryCollection;
+}
+
+function main() {
+ const GEOMETRY_DATA_FILES = ['geometry', 'states-provinces-lines'];
+ const POINT_DATA_FILES = ['countries', 'cities'];
+ const OUTPUT_DIR = path.join(__dirname, 'out');
+
+ for (const name of GEOMETRY_DATA_FILES) {
+ const source = path.join(OUTPUT_DIR, `${name}.json`);
+ const destination = path.join(OUTPUT_DIR, `${name}.rbush.json`);
+
+ try {
+ processGeometry(source, destination);
+ } catch (error) {
+ console.error(`Failed to process ${name}: ${error.message}`);
+ }
+ }
+
+ for (const name of POINT_DATA_FILES) {
+ const source = path.join(OUTPUT_DIR, `${name}.json`);
+ const destination = path.join(OUTPUT_DIR, `${name}.rbush.json`);
+
+ try {
+ processPoints(source, destination);
+ } catch (error) {
+ console.error(`Failed to process ${name}: ${error.message}`);
+ }
+ }
+}
+
+function processGeometry(source: string, destination: string) {
+ const collection = JSON.parse(fs.readFileSync(source, { encoding: 'utf8' })) as Topology<
+ GeometryTopologyObjects
+ >;
+
+ const { geometry } = collection.objects;
+ const treeData = geometry.geometries.map((object, i) => {
+ if (!object.bbox) {
+ throw new Error(`Expected a geometry at index ${i} to have a bbox property.`);
+ }
+
+ const [minX, minY, maxX, maxY] = object.bbox;
+ return {
+ ...object,
+ minX,
+ minY,
+ maxX,
+ maxY,
+ };
+ });
+
+ const tree = rbush();
+ tree.load(treeData);
+ fs.writeFileSync(destination, JSON.stringify(tree.toJSON()));
+
+ console.log(`Saved a rbush to ${destination}`);
+}
+
+function processPoints(source: string, destination: string) {
+ const collection = JSON.parse(fs.readFileSync(source, { encoding: 'utf8' })) as GeoJSON;
+
+ if (collection.type !== 'FeatureCollection') {
+ throw new Error(
+ `Invalid collection type ${collection.type} in ${source}. Expected FeatureCollection`,
+ );
+ }
+
+ const treeData = collection.features.map((feat) => {
+ if (feat.geometry.type !== 'Point') {
+ throw new Error(`Invalid geometry in ${source}. Expected "Point", got ${feat.geometry.type}`);
+ }
+
+ const { coordinates } = feat.geometry;
+ return {
+ ...feat,
+ minX: coordinates[0],
+ minY: coordinates[1],
+ maxX: coordinates[0],
+ maxY: coordinates[1],
+ };
+ });
+
+ const tree = rbush();
+ tree.load(treeData);
+ fs.writeFileSync(destination, JSON.stringify(tree.toJSON()));
+
+ console.log(`Saved a rbush to ${destination}`);
+}
+
+main();