diff --git a/README.md b/README.md index ea23c2a..61b281d 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ This package is a direct Node.js/TypeScript port of the excellent Python library While bringing these capabilities natively to the javascript ecosystem, we built and added several critical enhancements designed specifically for web applications and browser performance: -- **Aggressive Geometry Simplification:** Natively integrates `@turf/simplify` (0.001 tolerance, high-quality) to instantly compress raw unoptimized 25MB boundary polygons down to ~1MB browser-friendly payloads. +- **Aggressive Geometry Simplification:** Natively integrates `@turf/simplify` and `@turf/truncate` with a configurable `resolution` parameter (1=full detail, 10=max simplification, default=4). Compresses raw unoptimized 25MB boundary polygons down to ~1MB browser-friendly payloads while rounding all coordinates (geometry + GHS metadata) to 5 decimal places. - **Unified Cascading Caches:** Intelligent caching ladders that auto-resolve across global `process.env.GADM_CACHE`, active `process.cwd()`, and local workspace `../cache` mounts. - **Target-Level Subdivision Extraction:** A unified `targetLevel` API design that distinctly differentiates between extracting an outer merged geographic perimeter vs. an array of granular inner subdivided states natively derived from recursive `.merge()` operations. - **Smart Pre-cacher Script:** Includes `boundaries.ts`, an auto-resuming build script that iterates downwards to pre-calculate, dissolve, and aggressively compress hierarchy layers 0–5 for instant sub-ms API delivery, bypassing heavy mathematical geometry intersections at runtime. @@ -192,7 +192,7 @@ Higher-level API designed for HTTP handlers. Includes file-based caching via `GA | Function | Description | |----------|-------------| | `searchRegions(opts)` | Search by name, returns metadata or GeoJSON | -| `getBoundary(gadmId, contentLevel?, cache?)` | Get GeoJSON boundary for a GADM ID | +| `getBoundary(gadmId, contentLevel?, cache?, enrichOpts?, resolution?)` | Get GeoJSON boundary for a GADM ID | | `getRegionNames(opts)` | List sub-region names with depth control | #### Integration Example (Server API) @@ -311,13 +311,29 @@ When building interactive user interfaces or fetching boundaries through the top - **Outer Boundary**: Set `targetLevel` exactly equal to the region's intrinsic level (e.g., Targetting `Level 0` for Spain). The engine uses `turf` to automatically dissolve internal geometries, returning a single merged bounding polygon mimicking the total region envelope. - **Inner Subdivisions**: Provide a `targetLevel` deeper than the intrinsic level (e.g., Targetting `Level 1` for Spain). The engine filters for the exact constituent parts and returns a `FeatureCollection` where each active sub-group (the 17 Spanish States) is a distinctly preserved geometry feature. -### Smart Caching & Geometry Compression +### Geometry Simplification & Resolution + +Both the TypeScript and C++ pipelines apply geometry simplification controlled by a `resolution` parameter (default: **4**): + +| Resolution | Tolerance | Coordinate Precision | Use Case | +|------------|-----------|---------------------|----------| +| 1 | 0.0001 | 5 decimals | Maximum detail | +| 4 | 0.005 | 5 decimals | Default — good balance | +| 10 | 0.5 | 5 decimals | Maximum compression | + +The formula: `tolerance = 0.0001 * 10^((resolution-1) * 4/9)`. GHS metadata coordinates (`ghsPopCenter`, `ghsBuiltCenters`, etc.) are also rounded to 5 decimal places to match geometry precision. + +### Smart Caching & Cache Resolution Order To ensure instantaneous delivery (sub-10ms) of these polygons to your HTTP APIs: -1. **Pre-Caching Script**: You can run `npm run boundaries -- --country=all` manually. This script iterates downwards to compute and compress hierarchical layers 0 through 5 for each invoked country automatically. If a file already exists, it intelligently skips it allowing easy resume. -2. **Cascading Cache Lookups**: The package resolves caches intelligently by searching matching environments: First checking `process.env.GADM_CACHE` (used by explicit production APIs), then `process.cwd()/cache/gadm`, and finally its own local `../cache/gadm` workspace path. You can also actively inject an external Redis or memory cache interface providing `{ get(key), set(key, val) }` as the 3rd argument to `getBoundary`. -3. **Payload Compression (~25MB -> ~1MB)**: Boundary geometries are natively compressed using `@turf/simplify` (with `0.001` tolerance mapping to ~100m geospatial fidelity) immediately prior to caching, ensuring React mapping payloads stay tightly optimized and smooth without crashing browsers. +1. **Pre-Caching Scripts**: Run `npm run boundaries -- --country=all` (TypeScript) or `npm run boundaries:cpp` (C++). Both iterate downwards to compute and compress hierarchical layers 0 through 5 for each country. Existing files are skipped for easy resume. +2. **Cascading Cache Lookups**: The package resolves caches in order: + - Exact sub-region cache file: `boundary_{gadmId}_{level}.json` + - Full country cache file: `boundary_{countryCode}_{level}.json` (prefix-filtered for sub-region queries) + - Environment paths: `process.env.GADM_CACHE`, then `process.cwd()/cache/gadm`, then `../cache/gadm` + - Live GeoPackage query (fallback) +3. **Payload Compression (~25MB -> ~1MB)**: Boundary geometries are compressed using `@turf/simplify` (TS) or GEOS `GEOSSimplify_r` (C++) with matching tolerance, ensuring consistent output from both pipelines. --- @@ -420,15 +436,17 @@ For full batch generation across all 263 countries × 6 levels, the native C++ p ```bash # Build (requires vcpkg + CMake) -cmake --preset vcpkg-win -cmake --build cpp/build --config Release +npm run build:cpp # or: cmake --build cpp/build --config Release # Run via npm scripts -npm run boundaries:cpp # all countries -npm run boundaries:cpp -- --country=DEU # single country +npm run boundaries:cpp # all countries +npm run boundaries:cpp -- --country=DEU # single country -# Or directly -.\dist\win-x64\boundaries.exe --country=DEU --level=0 --force +# Sub-region splitting (generates boundary_ESP.6_1_4.json etc.) +npm run boundaries:cpp -- --country=all --level=4 --split-levels=1 + +# Custom resolution (1-10, default=4) +npm run boundaries:cpp -- --country=DEU --resolution=6 ``` Output includes GHS enrichment by default when tiff files are present in `data/ghs/`: @@ -505,15 +523,24 @@ JSON outputs saved to `tests/tree/` for inspection: ``` packages/gadm/ +├── cpp/ # C++ native pipeline (GDAL/GEOS/PROJ) +│ ├── src/ # main.cpp, gpkg_reader, geo_merge, ghs_enrich +│ ├── CMakeLists.txt +│ └── vcpkg.json ├── data/ │ ├── gadm_database.parquet # 356K rows, 6.29 MB -│ └── gadm_continent.json # Continent → ISO3 mapping +│ ├── gadm_continent.json # Continent → ISO3 mapping +│ └── ghs/ # GHS GeoTIFF rasters (optional) +├── dist/ +│ └── win-x64/ # Compiled C++ binary + DLLs ├── scripts/ │ └── refresh-database.ts # GeoPackage → Parquet converter ├── src/ │ ├── database.ts # Parquet reader (hyparquet) │ ├── names.ts # Name/code lookup + fuzzy match │ ├── items.ts # GeoJSON boundaries from CDN +│ ├── gpkg-reader.ts # GeoPackage boundary reader + C++ cache fallback +│ ├── enrich-ghs.ts # GHS GeoTIFF enrichment (TS) │ ├── wrapper.ts # Server-facing API with cache │ ├── tree.ts # Tree builder + iterators │ ├── index.ts # Barrel exports diff --git a/cpp/README.md b/cpp/README.md index b690cbd..550d981 100644 --- a/cpp/README.md +++ b/cpp/README.md @@ -52,27 +52,36 @@ Output: `dist/linux-x64/boundaries` + `proj.db` # From the gadm package root (not cpp/) # All countries, all levels (263 countries x 6 levels) -# Windows: .\dist\win-x64\boundaries.exe --country=all -# Linux: -./dist/linux-x64/boundaries --country=all # Single country, all levels -./dist/linux-x64/boundaries --country=DEU +.\dist\win-x64\boundaries.exe --country=DEU # Single country + level -./dist/linux-x64/boundaries --country=DEU --level=0 +.\dist\win-x64\boundaries.exe --country=DEU --level=0 + +# Sub-region specific (dotted GADM ID) +.\dist\win-x64\boundaries.exe --country=ESP.6_1 --level=4 + +# Batch sub-region generation for ALL countries +# Generates boundary_ESP.6_1_4.json, boundary_DEU.2_1_3.json, etc. +.\dist\win-x64\boundaries.exe --country=all --level=4 --split-levels=1 + +# Custom resolution (1=full detail, 10=max simplification, default=4) +.\dist\win-x64\boundaries.exe --country=DEU --resolution=6 # Force regeneration (ignore cached files) -./dist/linux-x64/boundaries --country=NGA --force +.\dist\win-x64\boundaries.exe --country=NGA --force ``` ### CLI Options | Option | Default | Description | |--------|---------|-------------| -| `--country` | `all` | ISO3 code or `all` for batch | +| `--country` | `all` | ISO3 code, dotted GADM ID (e.g. `ESP.6_1`), or `all` for batch | | `--level` | `-1` | Admin level 0-5, or -1 for all | +| `--split-levels` | `0` | Comma-separated list of levels to split output files by (e.g. `0,1`) | +| `--resolution` | `4` | Simplification resolution (1=full detail, 10=max simplification) | | `--cache-dir` | `cache/gadm` | Output directory | | `--gpkg` | `data/gadm_410-levels.gpkg` | GADM GeoPackage | | `--continent-json` | `data/gadm_continent.json` | Continent mapping | @@ -80,20 +89,34 @@ Output: `dist/linux-x64/boundaries` + `proj.db` | `--built-tiff` | `data/ghs/GHS_BUILT_S_...tif` | GHS built-up raster | | `--force` | `false` | Regenerate even if cached | +#### `--split-levels` explained + +By default (`--split-levels=0`), the tool outputs one file per country per level: `boundary_ESP_4.json`. + +With `--split-levels=1`, it dynamically queries all distinct level-1 region codes (e.g. `ESP.6_1`, `ESP.1_1`, …) and outputs individual files like `boundary_ESP.6_1_4.json`. This is useful for pre-splitting large countries into smaller, faster-loading cache files. + +The TS wrapper automatically discovers these sub-region files before falling back to the full country file. + ### npm Scripts ```bash -npm run boundaries:cpp # --country=all (full batch, Windows) -npm run boundaries:cpp -- --country=DEU # single country +npm run build:cpp # rebuild the C++ binary +npm run boundaries:cpp # --country=all (full batch, Windows) +npm run boundaries:cpp -- --country=DEU # single country ``` On Linux, run the binary directly since the npm script points to the Windows path. ## Output -Files written to `cache/gadm/boundary_{CODE}_{LEVEL}.json` — drop-in replacement for the TS pipeline. +Files written to `cache/gadm/` as: +- `boundary_{CODE}_{LEVEL}.json` — full country file (e.g. `boundary_ESP_4.json`) +- `boundary_{GADM_ID}_{LEVEL}.json` — sub-region file when `--split-levels` is used (e.g. `boundary_ESP.6_1_4.json`) -The TS wrapper (`gpkg-reader.ts`) automatically discovers these cache files and serves them through the API. Sub-region queries (e.g. `getBoundary('DEU.2_1', 3)`) are resolved by prefix-filtering the full country file. +The TS wrapper (`gpkg-reader.ts`) resolves cache files in this order: +1. Exact sub-region file: `boundary_{gadmId}_{level}.json` +2. Full country file: `boundary_{countryCode}_{level}.json` (prefix-filtered for sub-region queries) +3. Live GeoPackage query (fallback) Each feature includes: - `code` — admin region code diff --git a/cpp/src/gpkg_reader.cpp b/cpp/src/gpkg_reader.cpp index be0a461..dce4cf1 100644 --- a/cpp/src/gpkg_reader.cpp +++ b/cpp/src/gpkg_reader.cpp @@ -15,12 +15,7 @@ namespace gpkg_reader { static GDALDatasetH g_ds = nullptr; static std::string g_current_gpkg = ""; -std::vector read_features( - const std::string& gpkg_path, - const std::string& country_code, - int level, - double tolerance -) { +static void ensure_open(const std::string& gpkg_path) { if (!g_ds || g_current_gpkg != gpkg_path) { if (g_ds) GDALClose(g_ds); GDALAllRegister(); @@ -52,9 +47,60 @@ std::vector read_features( } g_current_gpkg = gpkg_path; } +} + +std::vector get_subregions( + const std::string& gpkg_path, + const std::string& country_code, + int split_level +) { + ensure_open(gpkg_path); + GDALDatasetH ds = g_ds; + + std::string layer_name = "ADM_ADM_" + std::to_string(split_level); + OGRLayerH layer = GDALDatasetGetLayerByName(ds, layer_name.c_str()); + if (!layer) { + layer = GDALDatasetGetLayer(ds, split_level); + if (!layer) layer = GDALDatasetGetLayer(ds, 0); + } + if (!layer) return {}; + + std::string actual_layer_name = OGR_L_GetName(layer); + std::string sql = "SELECT DISTINCT GID_" + std::to_string(split_level) + " FROM \"" + actual_layer_name + "\" WHERE GID_0 = '" + country_code + "'"; + + OGRLayerH query_layer = GDALDatasetExecuteSQL(ds, sql.c_str(), nullptr, "SQLite"); + if (!query_layer) return {}; + + std::vector subregions; + OGRFeatureH feat; + OGR_L_ResetReading(query_layer); + while ((feat = OGR_L_GetNextFeature(query_layer)) != nullptr) { + const char* val = OGR_F_GetFieldAsString(feat, 0); + if (val) { + subregions.push_back(val); + } + OGR_F_Destroy(feat); + } + GDALDatasetReleaseResultSet(ds, query_layer); + + return subregions; +} + +std::vector read_features( + const std::string& gpkg_path, + const std::string& country_code, + int level, + double tolerance +) { + ensure_open(gpkg_path); GDALDatasetH ds = g_ds; + // Parse dot_count for country_code filtering (e.g. ESP.6_1) + std::string gadm_id = country_code; + int dot_count = std::count(gadm_id.begin(), gadm_id.end(), '.'); + std::string iso_code = dot_count > 0 ? gadm_id.substr(0, gadm_id.find('.')) : gadm_id; + // Find the correct layer and its actual name std::string layer_name = "ADM_ADM_" + std::to_string(level); OGRLayerH layer = GDALDatasetGetLayerByName(ds, layer_name.c_str()); @@ -67,12 +113,19 @@ std::vector read_features( std::string actual_layer_name = OGR_L_GetName(layer); // Execute SQL query directly via SQLite dialect to force index usage - std::string sql = "SELECT * FROM \"" + actual_layer_name + "\" WHERE GID_0 = '" + country_code + "'"; + std::string sql = "SELECT * FROM \"" + actual_layer_name + "\" WHERE GID_0 = '" + iso_code + "'"; + if (dot_count > 0 && dot_count <= level) { + sql += " AND GID_" + std::to_string(dot_count) + " = '" + gadm_id + "'"; + } OGRLayerH query_layer = GDALDatasetExecuteSQL(ds, sql.c_str(), nullptr, "SQLite"); if (!query_layer) { // Fallback to OGR filtering if ExecuteSQL fails - OGR_L_SetAttributeFilter(layer, ("GID_0 = '" + country_code + "'").c_str()); + std::string filter = "GID_0 = '" + iso_code + "'"; + if (dot_count > 0 && dot_count <= level) { + filter += " AND GID_" + std::to_string(dot_count) + " = '" + gadm_id + "'"; + } + OGR_L_SetAttributeFilter(layer, filter.c_str()); query_layer = layer; } @@ -114,7 +167,7 @@ std::vector read_features( bf.minY = env.MinY; bf.maxY = env.MaxY; - int wkbSize = OGR_G_WkbSize(out_geom); + size_t wkbSize = OGR_G_WkbSize(out_geom); bf.wkb.resize(wkbSize); OGR_G_ExportToWkb(out_geom, wkbNDR, bf.wkb.data()); diff --git a/cpp/src/gpkg_reader.h b/cpp/src/gpkg_reader.h index b22505b..223216f 100644 --- a/cpp/src/gpkg_reader.h +++ b/cpp/src/gpkg_reader.h @@ -9,6 +9,15 @@ namespace gpkg_reader { /// Read features from a GeoPackage file, filtered by country (GID_0) and admin level. /// Groups features by GID_{level} and returns one BoundaryFeature per group /// with its geometry as a GEOS handle. +/// Retrieve a list of distinct GID_{split_level} values for a given country code +std::vector get_subregions( + const std::string& gpkg_path, + const std::string& country_code, + int split_level +); + +/// Read features from a GeoPackage file, filtered by country (GID_0) and admin level. +/// Can also filter directly by sub-region if country_code is a dotted GADM ID (e.g. ESP.6_1). std::vector read_features( const std::string& gpkg_path, const std::string& country_code, diff --git a/cpp/src/main.cpp b/cpp/src/main.cpp index e41fc48..c75955d 100644 --- a/cpp/src/main.cpp +++ b/cpp/src/main.cpp @@ -44,7 +44,8 @@ int main(int argc, char *argv[]) { std::string pop_tiff = "data/ghs/GHS_POP_E2030_GLOBE_R2023A_54009_100_V1_0.tif"; std::string built_tiff = "data/ghs/GHS_BUILT_S_E2030_GLOBE_R2023A_54009_100_V1_0.tif"; bool force = false; - int resolution = 1; + int resolution = 4; // Use 4 as default matching the TS wrapper + std::vector split_levels = {0}; app.add_option("--country", country, "ISO3 country code, or 'all' for batch") ->default_val("all"); @@ -64,7 +65,10 @@ int main(int argc, char *argv[]) { ->default_val("data/ghs/GHS_BUILT_S_E2030_GLOBE_R2023A_54009_100_V1_0.tif"); app.add_flag("--force", force, "Regenerate even if cache file exists"); app.add_option("--resolution", resolution, "Simplification resolution (1=full to 10=max simplification)") - ->default_val(1); + ->default_val(4); + app.add_option("--split-levels", split_levels, "Comma-separated levels to split output files (e.g. 1,2,3)") + ->default_val(std::vector{0}) + ->delimiter(','); CLI11_PARSE(app, argc, argv); @@ -161,26 +165,37 @@ int main(int argc, char *argv[]) { const auto &code = countries[i]; for (int lvl : levels) { - std::string filename = - "boundary_" + code + "_" + std::to_string(lvl) + ".json"; - fs::path out_path = fs::path(cache_dir) / filename; + for (int split_lvl : split_levels) { + if (split_lvl > lvl) continue; - // Skip if cached - if (!force && file_exists(out_path)) { - ++skipped; - continue; - } - - try { - // 1. Read features from GeoPackage - auto t0 = std::chrono::high_resolution_clock::now(); - auto features = gpkg_reader::read_features(gpkg_path, code, lvl, tolerance); - auto t1 = std::chrono::high_resolution_clock::now(); - if (features.empty()) { - ++skipped; - continue; + std::vector regions; + if (split_lvl == 0) { + regions.push_back(code); + } else { + regions = gpkg_reader::get_subregions(gpkg_path, code, split_lvl); } + for (const auto& region_id : regions) { + std::string filename = + "boundary_" + region_id + "_" + std::to_string(lvl) + ".json"; + fs::path out_path = fs::path(cache_dir) / filename; + + // Skip if cached + if (!force && file_exists(out_path)) { + ++skipped; + continue; + } + + try { + // 1. Read features from GeoPackage + auto t0 = std::chrono::high_resolution_clock::now(); + auto features = gpkg_reader::read_features(gpkg_path, region_id, lvl, tolerance); + auto t1 = std::chrono::high_resolution_clock::now(); + if (features.empty()) { + ++skipped; + continue; + } + // 2. Merge geometries auto merged = geo_merge::merge(features); auto t2 = std::chrono::high_resolution_clock::now(); @@ -201,7 +216,7 @@ int main(int argc, char *argv[]) { props["NAME_" + std::to_string(lvl)] = feat.name; props["GID_" + std::to_string(lvl)] = feat.code; - int dotCount = std::count(feat.code.begin(), feat.code.end(), '.'); + int dotCount = static_cast(std::count(feat.code.begin(), feat.code.end(), '.')); if (lvl == dotCount) { props["isOuter"] = true; } @@ -261,9 +276,11 @@ int main(int argc, char *argv[]) { "write:" + std::to_string(ms_write) + "ms " + "Total:" + std::to_string(ms_total) + "ms"); - } catch (const std::exception &e) { - ++errors; - logger::error(code + " L" + std::to_string(lvl) + ": " + e.what()); + } catch (const std::exception &e) { + ++errors; + logger::error(region_id + " L" + std::to_string(lvl) + ": " + e.what()); + } + } } } } diff --git a/dist/gpkg-reader.js b/dist/gpkg-reader.js index d96afef..f6d082a 100644 --- a/dist/gpkg-reader.js +++ b/dist/gpkg-reader.js @@ -349,41 +349,55 @@ export async function getBoundaryFromGpkg(gadmId, contentLevel, externalCache, r const gidLevel = dotCount; const resolvedLevel = contentLevel != null ? contentLevel : gidLevel; const countryCode = gadmId.split('.')[0]; - const cppFileName = `boundary_${countryCode}_${resolvedLevel}.json`; - // Build a prefix for sub-region filtering: - // 'DEU' (country-level) → no filter needed, return all features - // 'DEU.2_1' → prefix 'DEU.2.' matches DEU.2.91_1, DEU.2.91.1_1, etc. + // C++ outputs sub-region precise files too if batched with `--split-levels`. + // We look for exact gadmId match first, then fall back to full country. + const fallbackNames = [ + `boundary_${gadmId}_${resolvedLevel}.json`, + `boundary_${countryCode}_${resolvedLevel}.json` + ]; + // Remove duplicates if gadmId == countryCode + const uniqueFallbackNames = [...new Set(fallbackNames)]; + // Build a prefix for sub-region filtering (used mostly for the full-country fallback) const isSubRegion = gadmId.includes('.'); const gidPrefix = isSubRegion ? gadmId.replace(/_\d+$/, '') + '.' // strip version suffix, add dot : null; - for (const dir of uniqueCacheDirs) { - const cppFile = join(dir, cppFileName); - if (existsSync(cppFile)) { - try { - const raw = JSON.parse(readFileSync(cppFile, 'utf-8')); - if (raw.features && Array.isArray(raw.features)) { - console.log(`Loading from CPP Cache File ${cppFile} : ${gidPrefix}`); - let rawFeatures = raw.features; - // Filter by GID prefix for sub-region queries - if (gidPrefix) { - rawFeatures = rawFeatures.filter((f) => f.code && f.code.startsWith(gidPrefix)); + for (const cppFileName of uniqueFallbackNames) { + for (const dir of uniqueCacheDirs) { + const cppFile = join(dir, cppFileName); + if (existsSync(cppFile)) { + try { + const raw = JSON.parse(readFileSync(cppFile, 'utf-8')); + if (raw.features && Array.isArray(raw.features)) { + console.log(`[gpkg-reader] Loading from CPP Cache File ${cppFile} : ${gidPrefix || 'country-wide'}`); + let rawFeatures = raw.features; + // Filter by GID prefix if we had to read the fallback country-wide file + // (If we loaded the exact sub-region file, it's already perfectly chunked) + if (gidPrefix && cppFileName.includes(countryCode) && !cppFileName.includes(gadmId)) { + rawFeatures = rawFeatures.filter((f) => f.code && f.code.startsWith(gidPrefix)); + } if (rawFeatures.length === 0) continue; // no matches, try next dir + const features = rawFeatures.map((f) => { + const { geometry, code, name, ...enrichment } = f; + return { + type: 'Feature', + properties: { name, code, ...enrichment }, + geometry, + }; + }); + const result = { type: 'FeatureCollection', features }; + const outCacheFile = join(uniqueCacheDirs[1] || uniqueCacheDirs[0], `${cacheKey}.json`); + try { + writeFileSync(outCacheFile, JSON.stringify(result)); + } + catch (e) { /* ignore */ } + return result; } - const features = rawFeatures.map((f) => { - const { geometry, code, name, ...enrichment } = f; - return { - type: 'Feature', - properties: { name, code, ...enrichment }, - geometry, - }; - }); - return { type: 'FeatureCollection', features }; } - } - catch (e) { - console.warn(`[gpkg-reader] Failed to read C++ cache from ${cppFile}:`, e); + catch (e) { + console.warn(`[gpkg-reader] Failed to read C++ cache from ${cppFile}:`, e); + } } } } @@ -605,4 +619,4 @@ export function getHierarchyByPoint(lat, lon) { return null; } } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3BrZy1yZWFkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZ3BrZy1yZWFkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsT0FBTyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLFNBQVMsRUFBRSxNQUFNLElBQUksQ0FBQztBQUN4RSxPQUFPLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDOUMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUNwQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUV2RCxNQUFNLFNBQVMsR0FBRyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNqRCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7QUFvQnBDLHlDQUF5QztBQUV6QyxNQUFNLGtCQUFrQixHQUFHO0lBQ3ZCLHVDQUF1QztJQUN2QyxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWM7SUFDMUIsK0JBQStCO0lBQy9CLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsb0JBQW9CLENBQUM7SUFDNUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSwwQkFBMEIsQ0FBQztDQUNyRCxDQUFDO0FBRUYsSUFBSSxTQUFTLEdBQWtCLElBQUksQ0FBQztBQUVwQywrQ0FBK0M7QUFDL0MsTUFBTSxVQUFVLFdBQVcsQ0FBQyxDQUFTO0lBQ2pDLFNBQVMsR0FBRyxDQUFDLENBQUM7QUFDbEIsQ0FBQztBQUVELFNBQVMsUUFBUTtJQUNiLElBQUksU0FBUyxJQUFJLFVBQVUsQ0FBQyxTQUFTLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUN6RCxLQUFLLE1BQU0sQ0FBQyxJQUFJLGtCQUFrQixFQUFFLENB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 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3BrZy1yZWFkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZ3BrZy1yZWFkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsT0FBTyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLFNBQVMsRUFBRSxNQUFNLElBQUksQ0FBQztBQUN4RSxPQUFPLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDOUMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUNwQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUV2RCxNQUFNLFNBQVMsR0FBRyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNqRCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7QUFvQnBDLHlDQUF5QztBQUV6QyxNQUFNLGtCQUFrQixHQUFHO0lBQ3ZCLHVDQUF1QztJQUN2QyxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWM7SUFDMUIsK0JBQStCO0lBQy9CLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsb0JBQW9CLENBQUM7SUFDNUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSwwQkFBMEIsQ0FBQztDQUNyRCxDQUFDO0FBRUYsSUFBSSxTQUFTLEdBQWtCLElBQUksQ0FBQztBQUVwQywrQ0FBK0M7QUFDL0MsTUFBTSxVQUFVLFdBQVcsQ0FBQyxDQUFTO0lBQ2pDLFNBQVMsR0FBRyxDQUFDLENBQUM7QUFDbEIsQ0FBQztBQUVELFNBQVMsUUFBUTtJQUNiLElBQUksU0FBUyxJQUFJLFVBQVUsQ0FBQyxTQUFTLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUN6RCxLQUFLLE1BQU0sQ0FBQyxJQUFJLGtCQUFrQixFQUFFLENB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 \ No newline at end of file diff --git a/dist/win-x64/boundaries.exe b/dist/win-x64/boundaries.exe index fe81a58..c464bf5 100644 Binary files a/dist/win-x64/boundaries.exe and b/dist/win-x64/boundaries.exe differ diff --git a/docs/geo.md b/docs/geo.md new file mode 100644 index 0000000..97541cd --- /dev/null +++ b/docs/geo.md @@ -0,0 +1,40 @@ +# Geospatial Architecture & Rendering Strategy + +This document outlines the architectural decisions and trade-offs regarding how we process, store, and render GADM administrative boundaries in our web application using MapLibre GL JS. + +## The Problem: High-Resolution Boundaries vs. Web Performance + +GADM boundaries are highly accurate and meticulously detailed. A single raw boundary for a Region/Level 2 area (like a large province in Poland) can easily exceed 5MB in its raw GeoJSON format. + +Sending 5MB+ payloads to a frontend map client to render a basic region outline is an architectural anti-pattern for several reasons: +- **Bandwidth:** High download times break the fluidity of the app, especially on slower connections or mobile devices. +- **Parsing Overhead:** Browsers struggle and block the main thread when parsing JSON payloads of this size. +- **Rendering Lag:** Rendering hundreds of thousands of microscopic, tightly-packed vertices degrades panning and zooming performance because the GPU is forced to process unneeded geometry. + +## Evaluation of Architectural Approaches + +### 1. Geometry Simplification (Chosen Approach) +Instead of serving 100% full-resolution geometries, we apply a geometry simplification algorithm (such as Douglas-Peucker via `OGR_G_SimplifyPreserveTopology` in GDAL) during the backend C++ pipeline step before the files are saved to the cache. + +By using a small geographical tolerance (e.g., `0.001` to `0.005` degrees), we eliminate up to 90-95% of vertices that lie essentially on a straight line. +- **Pros:** A 5MB file drops to ~100-200KB with zero visually perceptible difference at standard region-view zoom levels. It is extremely easy to cache and serve over a standard API without changing the frontend geometry-loading concepts. +- **Cons:** Shared borders between different polygons can sometimes develop tiny gaps or slivers if simplified individually without a shared topological graph/mesh. + +### 2. Mapbox Vector Tiles (MVT / Protocol Buffers) +Instead of returning monolithic GeoJSON boundary files, the map client natively requests data in small 256x256 pixel binary tiles (`.mvt` or `.pbf`). The geometries within these tiles are aggressively simplified and clipped based on the user's current zoom level. +- **Pros:** Phenomenal performance for rendering global, tremendously heavy datasets. Only data intersecting the user's viewport is loaded at any given time. +- **Cons:** High infrastructure overhead. It requires running an active live tile server (like `pg_tileserv` or `martin`) or pre-generating massive pyramidal tile caches (e.g., using `tippecanoe`). + +### 3. TopoJSON +An extension of GeoJSON that encodes *topology* rather than discrete geometries. Shared borders between adjacent regions are only recorded once. +- **Pros:** Can shrink file sizes by up to 80% compared to GeoJSON. Completely eliminates topological gaps when scaling/simplifying. +- **Cons:** Requires the frontend to bundle and run `topojson-client` to decode the data back into GeoJSON on-the-fly before MapLibre can consume it natively. + +## Conclusion & Current Direction + +Given our specific usecase: **We are loading boundaries into MapLibre primarily to display outlines and population centers for *certain/selected* GADM regions, rather than rendering the entire administrative globe all at once.** + +Because we are operating on an "on-demand, selected region" basis, setting up a full-blown Vector Tile infrastructure (Option 2) introduces unnecessary complexity. + +**Our strategy is to leverage Option 1: Pre-cached, heavily simplified GeoJSON.** +By applying a GDAL geometry simplification threshold and limiting coordinate precision down to 5 decimal places during the C++ build pipeline, we yield lightweight, highly performant payloads that MapLibre can ingest natively. This solves the file size bottleneck while preserving our simple and highly efficient file-based caching architecture. diff --git a/package.json b/package.json index 70d43bf..ffc07c9 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ }, "scripts": { "build": "tsc", + "build:cpp": "cmake --build cpp/build --config Release", "dev": "tsc -w", "tests": "vitest run", "test:boundaries": "vitest run src/__tests__/boundary.test.ts", @@ -37,6 +38,7 @@ "boundaries": "npx tsx scripts/boundaries.ts", "boundaries:cpp": ".\\dist\\win-x64\\boundaries.exe", "boundaries:cpp:all": ".\\dist\\win-x64\\boundaries.exe --country=all", + "boundaries:cpp:all:split": ".\\dist\\win-x64\\boundaries.exe --country=all --split-levels=1,2", "boundaries:cpp:linux": "./dist/linux-x64/boundaries", "boundaries:cpp:linux:all": "./dist/linux-x64/boundaries --country=all", "refresh": "npx tsx scripts/refresh-database.ts" @@ -60,4 +62,4 @@ "simplify-js": "1.2.4", "zod": "^4.3.6" } -} +} \ No newline at end of file diff --git a/src/gpkg-reader.ts b/src/gpkg-reader.ts index bc16b28..d974d77 100644 --- a/src/gpkg-reader.ts +++ b/src/gpkg-reader.ts @@ -415,46 +415,63 @@ export async function getBoundaryFromGpkg( const gidLevel = dotCount; const resolvedLevel = contentLevel != null ? contentLevel : gidLevel; const countryCode = gadmId.split('.')[0]; - const cppFileName = `boundary_${countryCode}_${resolvedLevel}.json`; + + // C++ outputs sub-region precise files too if batched with `--split-levels`. + // We look for exact gadmId match first, then fall back to full country. + const fallbackNames = [ + `boundary_${gadmId}_${resolvedLevel}.json`, + `boundary_${countryCode}_${resolvedLevel}.json` + ]; + + // Remove duplicates if gadmId == countryCode + const uniqueFallbackNames = [...new Set(fallbackNames)]; - // Build a prefix for sub-region filtering: - // 'DEU' (country-level) → no filter needed, return all features - // 'DEU.2_1' → prefix 'DEU.2.' matches DEU.2.91_1, DEU.2.91.1_1, etc. + // Build a prefix for sub-region filtering (used mostly for the full-country fallback) const isSubRegion = gadmId.includes('.'); const gidPrefix = isSubRegion ? gadmId.replace(/_\d+$/, '') + '.' // strip version suffix, add dot : null; - for (const dir of uniqueCacheDirs) { - const cppFile = join(dir, cppFileName); - if (existsSync(cppFile)) { - try { - const raw = JSON.parse(readFileSync(cppFile, 'utf-8')); - if (raw.features && Array.isArray(raw.features)) { - console.log(`Loading from CPP Cache File ${cppFile} : ${gidPrefix}`) + for (const cppFileName of uniqueFallbackNames) { + for (const dir of uniqueCacheDirs) { + const cppFile = join(dir, cppFileName); + if (existsSync(cppFile)) { + try { + const raw = JSON.parse(readFileSync(cppFile, 'utf-8')); + if (raw.features && Array.isArray(raw.features)) { + console.log(`[gpkg-reader] Loading from CPP Cache File ${cppFile} : ${gidPrefix || 'country-wide'}`) - let rawFeatures = raw.features; + let rawFeatures = raw.features; + + // Filter by GID prefix if we had to read the fallback country-wide file + // (If we loaded the exact sub-region file, it's already perfectly chunked) + if (gidPrefix && cppFileName.includes(countryCode) && !cppFileName.includes(gadmId)) { + rawFeatures = rawFeatures.filter((f: any) => + f.code && f.code.startsWith(gidPrefix) + ); + } - // Filter by GID prefix for sub-region queries - if (gidPrefix) { - rawFeatures = rawFeatures.filter((f: any) => - f.code && f.code.startsWith(gidPrefix) - ); if (rawFeatures.length === 0) continue; // no matches, try next dir - } - const features: BoundaryFeature[] = rawFeatures.map((f: any) => { - const { geometry, code, name, ...enrichment } = f; - return { - type: 'Feature' as const, - properties: { name, code, ...enrichment }, - geometry, - }; - }); - return { type: 'FeatureCollection', features }; + const features: BoundaryFeature[] = rawFeatures.map((f: any) => { + const { geometry, code, name, ...enrichment } = f; + return { + type: 'Feature' as const, + properties: { name, code, ...enrichment }, + geometry, + }; + }); + + const result: BoundaryResult = { type: 'FeatureCollection', features }; + const outCacheFile = join(uniqueCacheDirs[1] || uniqueCacheDirs[0], `${cacheKey}.json`); + try { + writeFileSync(outCacheFile, JSON.stringify(result)); + } catch (e) { /* ignore */ } + return result; + } + } catch (e) { + console.warn(`[gpkg-reader] Failed to read C++ cache from ${cppFile}:`, e); } - } catch (e) { - console.warn(`[gpkg-reader] Failed to read C++ cache from ${cppFile}:`, e); } } }