Wire offline hiking trails into the real build, API, and renderer
data/hiking_trails.geojson now generates automatically as the last step of every offline.pmtiles build (PmtilesBuilder.extract_hiking_trails, best-effort — a failure here doesn't fail the whole build), merged across all selected countries with cross-border dedup by OSM relation id (HikingTrails.extract_merged). Served at GET /tiles/hiking_trails.geojson and GET /api/hiking-trails, fetched client-side only once the overlay is actually toggled on. hiking_trails.js now prefers this local file whenever it exists, regardless of which base map (online/offline) is active — same "prefer local when available" story as HillshadeControl already uses for terrain. Offline click hit-tests the real vector layer directly (queryRenderedFeatures) instead of querying Overpass — instant, no network. Coordinates are rounded to 5dp to keep the combined file smaller; colour tag values are normalized against a known-safe set before ever reaching a style paint property. Verified extract_merged (new: combines multiple countries' extracts, dedupes overlapping relations) against two real cached country PBFs on brick directly, not just fixtures.
This commit is contained in:
1 parent
b35ace9734
commit
079ac37787
11 files changed
+370
-25
No files matched your search
@@ -76,6 +76,27 @@ class PmtilesBuilderTest < Minitest::Test
|
||||
SH
|
||||
File.chmod(0o755, @osmium_ok)
|
||||
|
||||
# Same shape as osmium-ok, but fails on tags-filter specifically (the
|
||||
# first subcommand HikingTrails.extract runs) while still succeeding
|
||||
# on merge — lets a single-country build (which never calls merge)
|
||||
# exercise "hiking-trails extraction failed" without also breaking
|
||||
# offline.pmtiles' own osmium use in a multi-country test.
|
||||
@osmium_fail_tags_filter = File.join(@bin_dir, "osmium-fail-tags-filter")
|
||||
File.write(@osmium_fail_tags_filter, <<~SH)
|
||||
#!/bin/sh
|
||||
echo "osmium $1" >> "$PMTILES_LOG"
|
||||
if [ "$1" = "tags-filter" ]; then
|
||||
echo "boom" >&2
|
||||
exit 1
|
||||
fi
|
||||
prev=""
|
||||
for arg; do
|
||||
if [ "$prev" = "-o" ]; then echo fake > "$arg"; fi
|
||||
prev="$arg"
|
||||
done
|
||||
SH
|
||||
File.chmod(0o755, @osmium_fail_tags_filter)
|
||||
|
||||
# Stands in for `java -jar planetiler.jar --osm-path=... --output=OUT`
|
||||
# — PLANETILER_JAR itself is irrelevant here (this fake ignores -jar's
|
||||
# argument entirely), only JAVA_BIN needs pointing at it.
|
||||
@@ -188,13 +209,42 @@ class PmtilesBuilderTest < Minitest::Test
|
||||
assert_path_exists File.join(@data_dir, "offline.pmtiles")
|
||||
refute_path_exists File.join(@data_dir, "offline.tmp.pmtiles")
|
||||
assert_equal "done", Maptool::PmtilesBuilder.offline_status[:state]
|
||||
assert_equal ["planetiler --osm-path"], log_lines
|
||||
assert_equal ["planetiler --osm-path", "osmium tags-filter", "osmium add-locations-to-ways", "osmium cat"], log_lines
|
||||
assert_equal(
|
||||
{ "sources" => [{ "code" => "SK", "slug" => "europe/slovakia", "last_modified" => "Wed, 10 Sep 2026 08:00:01 GMT" }] },
|
||||
Maptool::PmtilesBuilder.offline_meta(@data_dir),
|
||||
)
|
||||
end
|
||||
|
||||
def test_build_offline_also_writes_a_hiking_trails_geojson
|
||||
select_regions("SK")
|
||||
thread = Maptool::PmtilesBuilder.build_offline(data_dir: @data_dir, download_extract: fake_download)
|
||||
thread.join
|
||||
|
||||
# The fake osmium binary doesn't produce real OPL output, just
|
||||
# confirms the file lands and is valid (empty) GeoJSON — the real
|
||||
# parsing logic is covered by test_hiking_trails.rb against real OPL
|
||||
# fixtures.
|
||||
path = File.join(@data_dir, "hiking_trails.geojson")
|
||||
assert_path_exists path
|
||||
assert_equal({ "type" => "FeatureCollection", "features" => [] }, JSON.parse(File.read(path)))
|
||||
end
|
||||
|
||||
# The actual reasoning: hiking trails are a bonus overlay bolted onto the
|
||||
# existing offline.pmtiles build, not the core map — an osmium hiccup on
|
||||
# this one step shouldn't take down an otherwise-successful build.
|
||||
def test_build_offline_still_succeeds_when_hiking_trails_extraction_fails
|
||||
select_regions("SK")
|
||||
ENV["OSMIUM_BIN"] = @osmium_fail_tags_filter
|
||||
thread = Maptool::PmtilesBuilder.build_offline(data_dir: @data_dir, download_extract: fake_download)
|
||||
thread.join
|
||||
|
||||
assert_path_exists File.join(@data_dir, "offline.pmtiles")
|
||||
assert_equal "done", Maptool::PmtilesBuilder.offline_status[:state]
|
||||
refute_path_exists File.join(@data_dir, "hiking_trails.geojson")
|
||||
refute_path_exists "#{File.join(@data_dir, "hiking_trails.geojson")}.tmp"
|
||||
end
|
||||
|
||||
# Two countries selected — osmium merge should run before planetiler,
|
||||
# each downloaded source recorded in the sidecar meta.
|
||||
def test_build_offline_merges_multiple_selected_countries
|
||||
@@ -203,7 +253,14 @@ class PmtilesBuilderTest < Minitest::Test
|
||||
thread.join
|
||||
|
||||
assert_equal "done", Maptool::PmtilesBuilder.offline_status[:state]
|
||||
assert_equal ["osmium merge", "planetiler --osm-path"], log_lines
|
||||
assert_equal(
|
||||
[
|
||||
"osmium merge", "planetiler --osm-path",
|
||||
"osmium tags-filter", "osmium add-locations-to-ways", "osmium cat", # SK's own hiking-trails extraction
|
||||
"osmium tags-filter", "osmium add-locations-to-ways", "osmium cat", # AT's own
|
||||
],
|
||||
log_lines,
|
||||
)
|
||||
codes = Maptool::PmtilesBuilder.offline_meta(@data_dir)["sources"].map { |s| s["code"] }
|
||||
assert_equal %w[SK AT], codes
|
||||
end
|
||||
|
||||
Reference in new issue
Block a user