scripts/make_countries.js (161 lines of code) (raw):

#!/usr/bin/env node /* * Copyright 2023 Uber Technologies, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** @file make_countries.js * @brief Script to make country test fixtures based on Natural Earth data. * This makes the fixture with polygonToCells benchmarks. */ const fs = require('fs'); const path = require('path'); const https = require('https'); // Using GeoJSON version as it is easy to convert const SOURCE_URL = 'https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_50m_admin_0_countries.geojson'; const TARGET = process.argv[2]; // Use Node HTTPS module for download, to avoid dependencies function getSource(url) { return new Promise((resolve, reject) => { https.get(url, (resp) => { let data = ''; resp.on('data', (chunk) => { data += chunk; }); resp.on('end', () => { resolve(data); }); }).on('error', reject); }); } function degsToRads(deg) { return (deg * Math.PI) / 180; } function formatCoord([lng, lat]) { return `{${degsToRads(lat)}, ${degsToRads(lng)}}`; } function formatGeoLoop(loop) { return `{ .numVerts = ${loop.length}, .verts = (LatLng[]) { ${loop.map(formatCoord).join(',\n')} } }` } function formatGeoPolygon(poly, {i, name, verts}) { const holes = poly.slice(1); return ` // ${i}. ${name} (${verts} verts) { .geoloop = ${formatGeoLoop(poly[0])}, .numHoles = ${holes.length}${holes.length ? `, .holes = (GeoLoop[]) { ${holes.map(formatGeoLoop).join(',\n')} }` : ''} }` } async function makeCountries(sourceUrl, targetPath) { console.log(`Downloading from ${sourceUrl}...`) const countriesJson = await getSource(sourceUrl); const countries = JSON.parse(countriesJson); console.log(`Download completed, found ${countries.features.length} countries`); const polygons = []; const names = []; let i = 0; for (const {geometry, properties: {ADMIN: name}} of countries.features) { if (geometry.type === 'Polygon') { polygons.push(geometry.coordinates); names.push({i: String(i++), name, verts: geometry.coordinates[0].length}); } else if (geometry.type === 'MultiPolygon') { for (const poly of geometry.coordinates) { polygons.push(poly); names.push({i: String(i++), name, verts: poly[0].length}); } } } console.log(`Found ${polygons.length} polygons`); // In order to only allocate memory once, we take the biggest size // at res 7, pad it, and size up based on powers of 7. This number was // empirically determined. const MAX_SIZE_RES_7 = 17544338; const out = `/* * Copyright 2023 Uber Technologies, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * This file is generated by scripts/make_countries.js. * Made with Natural Earth. Contains data from nvkelso/natural-earth-vector. * https://github.com/nvkelso/natural-earth-vector/blob/ca96624a56bd078437bca8184e78163e5039ad19/LICENSE.md */ #include "benchmark.h" #include "h3api.h" #include "mathExtensions.h" #include "polyfill.h" #include "polygon.h" const GeoPolygon COUNTRIES[${polygons.length}] = {${ polygons.map((poly, i) => formatGeoPolygon(poly, names[i])).join(',') }}; BEGIN_BENCHMARKS(); int MAX_RES = 5; int64_t numHexagons; H3Index *hexagons; for (int res = 0; res < MAX_RES + 1; res++) { printf("Res %d", res); BENCHMARK(polygonToCells_AllCountries1, 5, { for (int index = 0; index < ${polygons.length}; index++) { H3_EXPORT(maxPolygonToCellsSize)(&COUNTRIES[index], res, CONTAINMENT_CENTER, &numHexagons); hexagons = calloc(numHexagons, sizeof(H3Index)); H3_EXPORT(polygonToCells)(&COUNTRIES[index], res, CONTAINMENT_CENTER, hexagons); free(hexagons); } }); BENCHMARK(polygonToCells_AllCountries2, 5, { for (int index = 0; index < ${polygons.length}; index++) { H3_EXPORT(maxPolygonToCellsSizeExperimental)(&COUNTRIES[index], res, CONTAINMENT_CENTER, &numHexagons); hexagons = calloc(numHexagons, sizeof(H3Index)); H3_EXPORT(polygonToCellsExperimental)(&COUNTRIES[index], res, CONTAINMENT_CENTER, numHexagons, hexagons); free(hexagons); } }); BENCHMARK(polygonToCells_AllCountries3, 5, { for (int index = 0; index < ${polygons.length}; index++) { H3_EXPORT(maxPolygonToCellsSizeExperimental)(&COUNTRIES[index], res, CONTAINMENT_CENTER, &numHexagons); hexagons = calloc(numHexagons, sizeof(H3Index)); H3_EXPORT(polygonToCellsExperimental)(&COUNTRIES[index], res, CONTAINMENT_FULL, numHexagons, hexagons); free(hexagons); } }); BENCHMARK(polygonToCells_AllCountries4, 5, { for (int index = 0; index < ${polygons.length}; index++) { H3_EXPORT(maxPolygonToCellsSizeExperimental)(&COUNTRIES[index], res, CONTAINMENT_CENTER, &numHexagons); hexagons = calloc(numHexagons, sizeof(H3Index)); H3_EXPORT(polygonToCellsExperimental)(&COUNTRIES[index], res, CONTAINMENT_OVERLAPPING, numHexagons, hexagons); free(hexagons); } }); } END_BENCHMARKS(); ` fs.mkdirSync(path.dirname(targetPath), { recursive:true }); fs.writeFileSync(targetPath, out, 'utf-8'); console.log(`Wrote fixture to ${targetPath}`); } makeCountries(SOURCE_URL, TARGET);