Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
7e70005
Added base case POI zoom in new MultiExpression
migurski Dec 26, 2025
3a62861
Moved initial zoom assignments to MultiExpression, seeing one unexpla…
migurski Dec 26, 2025
03316e2
Moved a bunch of high-zoom point logic to MultiExpression
migurski Dec 26, 2025
8821873
Created Matcher.SourceFeatureWithComputedTags() to allow mutation of …
migurski Dec 26, 2025
f7a4928
Fixed Matcher.SourceFeatureWithComputedTags() to require fewer signat…
migurski Dec 26, 2025
5c529a5
Moved SourceFeatureWithComputedTags construction into computeExtraTags
migurski Dec 26, 2025
5711a0e
Moved selected small-area polygons into rules
migurski Dec 26, 2025
8fa32b3
Moved some protomaps-basemaps: tags to private static strings
migurski Dec 26, 2025
8200a7c
Removed HashMap
migurski Dec 27, 2025
379cb91
Moved all college/university zooms to rules with new withinRange expr…
migurski Dec 27, 2025
d03004f
Fixed zoom rule ordering failure
migurski Dec 27, 2025
1ff3316
Moved assorted green and other zoom-based polygons to rules
migurski Dec 27, 2025
f2dbdf4
Moved schools, cemeteries, and national parks to zoom-graded rules
migurski Dec 27, 2025
cca5a64
Corrected withinRange() bounds logic and moved height adjustments to …
migurski Dec 27, 2025
4431fb3
Reorganized final adjustments for clarity
migurski Dec 27, 2025
1febd2e
Shorthanded a bunch of zoom rules
migurski Dec 27, 2025
1a59b25
Switched to overloaded withinRange() to allow for scientific notation…
migurski Dec 27, 2025
665645a
Moved last top-level tag checks in processOsm() to rules
migurski Dec 27, 2025
5dcb548
De-duped some final logic to clarify identical point/polygon POI beha…
migurski Dec 27, 2025
3a569b6
Renamed and organized zoom rules for legibility
migurski Dec 27, 2025
2525a5c
Tweak, tweak, tweak
migurski Dec 27, 2025
1982412
More tweak, tweak, tweak
migurski Dec 27, 2025
f0ea92a
Carved zoomsIndex into point-and-polygon-specific MultiExpressions
migurski Dec 27, 2025
479a5e4
Fixed overly-broad point matches on irrelevant tags
migurski Dec 27, 2025
415e587
Switched to constants for KIND and MINZOOM strings
migurski Dec 27, 2025
d619032
Cleanup
migurski Dec 27, 2025
2dfde30
Condensed some long booleans
migurski Dec 28, 2025
ed0399e
Uppercased more constants
migurski Dec 28, 2025
da5e34f
Bumped version number
migurski Dec 29, 2025
a349c4b
Applied automated code quality suggestions
migurski Dec 29, 2025
5f9a59f
Applied additional code quality suggestions
migurski Dec 29, 2025
85d6977
Committed trailing space removal in comment blocks due to .editorconf…
migurski Dec 29, 2025
792ec92
Replaced single-bound version of withinRange() by atLeast()
migurski Jan 5, 2026
4e9ef8b
Merge branch 'main' of https://github.com/protomaps/basemaps into mig…
migurski Jan 5, 2026
0f0a427
Recoded Claude-provided plan for Overture addition
migurski Dec 28, 2025
9d158b1
Added script to download Overture data as Parquet
migurski Dec 28, 2025
5100928
Updated Overture plan with some manual edits
migurski Dec 29, 2025
d184f3d
Implemented --overture CLI flag and got it working with just land & w…
migurski Dec 29, 2025
39bc167
Expanded Overture theme=base to landuse layer
migurski Dec 30, 2025
d3b937b
Added Overture theme=buildings to buildings layer
migurski Dec 30, 2025
3654f39
Added Overture theme=transportation to roads layer
migurski Dec 30, 2025
14bd973
Added Overture theme=places to pois layer
migurski Dec 30, 2025
ba28f22
Added first failing Overture POI tests
migurski Dec 30, 2025
bce832d
Added feature finder script to assist with Overture test cases
migurski Dec 30, 2025
e55ad3e
Sped up feature finder with RTree
migurski Dec 30, 2025
adc2883
Added more failing Overture POI tests
migurski Dec 30, 2025
60fc3e0
Replaced failing OGR SQL queries that were too long
migurski Dec 30, 2025
57f792e
Added failing Overture POI test
migurski Dec 30, 2025
2ba9b96
Sped up feature finder with more parallel ops
migurski Dec 30, 2025
1c09979
Added numerous failing RoadsTest cases
migurski Dec 31, 2025
eec3db5
Added failing trunk and motorway tests
migurski Dec 31, 2025
67eaba4
Added test for all classes of link roads
migurski Dec 31, 2025
5057890
Switched from raw tags to assigned kind in POI zooms to prepare for O…
migurski Dec 31, 2025
3eb6dfa
Passed all Overture POI tests by applying new rules
migurski Dec 31, 2025
26b1aab
Added QRank for Overture
migurski Dec 31, 2025
0adca8b
Added basic kind assignments for Overture roads
migurski Dec 31, 2025
4ea04aa
Added basic zoom assignments for Overture roads
migurski Dec 31, 2025
3a35a57
Add comprehensive tests for Overture roads oneway/is_link extraction …
migurski Dec 31, 2025
0291908
Implement Overture roads line splitting for partial bridge/tunnel/one…
migurski Dec 31, 2025
1b4b172
Fix Linear.splitAtFractions() to preserve intermediate vertices for c…
migurski Dec 31, 2025
7e469de
Reimplemented Linear.java using existing JTS linear referencing support
migurski Dec 31, 2025
7da30b0
Fixed split geometry tests to correctly handle world coordinates
migurski Dec 31, 2025
385025f
Corrected oneway=yes to get arrows showing up
migurski Dec 31, 2025
5de599b
Minor cleanup
migurski Dec 31, 2025
14ad779
...
migurski Dec 31, 2025
e67bd22
Shortened some superlong function bodies
migurski Jan 1, 2026
e8c935c
Migrated OSM minZoom to highwayZoomsIndex
migurski Jan 1, 2026
9a0a636
Separated remaining zoom-related rules for OSM roads
migurski Jan 1, 2026
3b0d9e4
Claude's version of Places.java
migurski Jan 1, 2026
c5c233e
Organized Places rules to separate kinds and zooms indexes
migurski Jan 1, 2026
4abbab6
kindRank can come from osmKindsIndex (for now!) and zoomsIndex, but n…
migurski Jan 1, 2026
adf1744
Building parts look nice
migurski Jan 3, 2026
9da323b
Added rendering and tests for theme=transportation/type=segment rail …
migurski Jan 3, 2026
e1e8327
Delete outdated implementation plan
migurski Jan 4, 2026
03a5d92
Added basic Overture landcover
migurski Jan 5, 2026
2c5f725
Replaced Python scripts with https://gist.github.com/migurski/8765492…
migurski Jan 6, 2026
b80cb91
Bumped version to 4.14
migurski Jan 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
Tiles 4.14.0
------
- Add Overture data source support [#541]

Tiles 4.13.6
------
- Translate POI min_zoom= assignments to MultiExpression rules [#539]

Tiles 4.13.5
------
- Translate POI kind= assignments to MultiExpression rules [#537]
Expand Down
65 changes: 54 additions & 11 deletions tiles/src/main/java/com/protomaps/basemap/Basemap.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,37 +46,43 @@ public Basemap(QrankDb qrankDb, CountryCoder countryCoder, Clip clip,
var buildings = new Buildings();
registerHandler(buildings);
registerSourceHandler("osm", buildings::processOsm);
registerSourceHandler("overture", buildings::processOverture);
}

if (layer.isEmpty() || layer.equals(Landuse.LAYER_NAME)) {
var landuse = new Landuse();
registerHandler(landuse);
registerSourceHandler("osm", landuse::processOsm);
registerSourceHandler("overture", landuse::processOverture);
}

if (layer.isEmpty() || layer.equals(Landcover.LAYER_NAME)) {
var landcover = new Landcover();
registerHandler(landcover);
registerSourceHandler("landcover", landcover::processLandcover);
registerSourceHandler("ne", landcover::processNe);
registerSourceHandler("overture", landcover::processOverture);
}

if (layer.isEmpty() || layer.equals(Places.LAYER_NAME)) {
var place = new Places(countryCoder);
registerHandler(place);
registerSourceHandler("osm", place::processOsm);
registerSourceHandler("overture", place::processOverture);
}

if (layer.isEmpty() || layer.equals(Pois.LAYER_NAME)) {
var poi = new Pois(qrankDb);
registerHandler(poi);
registerSourceHandler("osm", poi::processOsm);
registerSourceHandler("overture", poi::processOverture);
}

if (layer.isEmpty() || layer.equals(Roads.LAYER_NAME)) {
var roads = new Roads(countryCoder);
registerHandler(roads);
registerSourceHandler("osm", roads::processOsm);
registerSourceHandler("overture", roads::processOverture);
}

if (layer.isEmpty() || layer.equals(Transit.LAYER_NAME)) {
Expand All @@ -91,6 +97,7 @@ public Basemap(QrankDb qrankDb, CountryCoder countryCoder, Clip clip,
registerSourceHandler("osm", water::processOsm);
registerSourceHandler("osm_water", water::processPreparedOsm);
registerSourceHandler("ne", water::processNe);
registerSourceHandler("overture", water::processOverture);
}

if (layer.isEmpty() || layer.equals(Earth.LAYER_NAME)) {
Expand All @@ -100,6 +107,7 @@ public Basemap(QrankDb qrankDb, CountryCoder countryCoder, Clip clip,
registerSourceHandler("osm", earth::processOsm);
registerSourceHandler("osm_land", earth::processPreparedOsm);
registerSourceHandler("ne", earth::processNe);
registerSourceHandler("overture", earth::processOverture);
}

if (clip != null) {
Expand All @@ -119,7 +127,7 @@ public String description() {

@Override
public String version() {
return "4.13.5";
return "4.14.0";
}

@Override
Expand Down Expand Up @@ -173,6 +181,7 @@ private static void printHelp() {
--help, -h Show this help message and exit
--area=<name> Geofabrik area name to download, or filename in data/sources/
(default: monaco, e.g., us/california, washington)
--overture=<path> Path to Overture Maps Parquet file (mutually exclusive with --area)
--maxzoom=<n> Maximum zoom level (default: 15)
--layer=<name> Process only a single layer (optional)
Valid values: boundaries, buildings, landuse, landcover,
Expand Down Expand Up @@ -209,17 +218,39 @@ static void run(Arguments args) throws IOException {

var countryCoder = CountryCoder.fromJarResource();

String area = args.getString("area", "Geofabrik area name to download, or filename in data/sources/", "monaco");
String area = args.getString("area", "Geofabrik area name to download, or filename in data/sources/", "");
String overtureFile = args.getString("overture", "Path to Overture Maps Parquet file", "");

if (!area.isEmpty() && !overtureFile.isEmpty()) {
LOGGER.error("Error: Cannot specify both --area and --overture");
System.exit(1);
}
if (area.isEmpty() && overtureFile.isEmpty()) {
area = "monaco"; // default
}

var planetiler = Planetiler.create(args)
.addNaturalEarthSource("ne", nePath, neUrl)
.addOsmSource("osm", Path.of("data", "sources", area + ".osm.pbf"), "geofabrik:" + area)
.addShapefileSource("osm_water", sourcesDir.resolve("water-polygons-split-3857.zip"),
"https://osmdata.openstreetmap.de/download/water-polygons-split-3857.zip")
.addShapefileSource("osm_land", sourcesDir.resolve("land-polygons-split-3857.zip"),
"https://osmdata.openstreetmap.de/download/land-polygons-split-3857.zip")
.addGeoPackageSource("landcover", sourcesDir.resolve("daylight-landcover.gpkg"),
"https://r2-public.protomaps.com/datasets/daylight-landcover.gpkg");
.addNaturalEarthSource("ne", nePath, neUrl);

if (!overtureFile.isEmpty()) {
// Add Overture Parquet source
planetiler.addParquetSource("overture",
List.of(Path.of(overtureFile)),
false, // not Hive partitioned dirname, just a single file
fields -> fields.get("id"),
fields -> fields.get("type") // source layer
);
} else {
// Add OSM and GeoPackage sources
planetiler
.addOsmSource("osm", Path.of("data", "sources", area + ".osm.pbf"), "geofabrik:" + area)
.addShapefileSource("osm_water", sourcesDir.resolve("water-polygons-split-3857.zip"),
"https://osmdata.openstreetmap.de/download/water-polygons-split-3857.zip")
.addShapefileSource("osm_land", sourcesDir.resolve("land-polygons-split-3857.zip"),
"https://osmdata.openstreetmap.de/download/land-polygons-split-3857.zip")
.addGeoPackageSource("landcover", sourcesDir.resolve("daylight-landcover.gpkg"),
"https://r2-public.protomaps.com/datasets/daylight-landcover.gpkg");
}

Path pgfEncodingZip = sourcesDir.resolve("pgf-encoding.zip");
Path qrankCsv = sourcesDir.resolve("qrank.csv.gz");
Expand Down Expand Up @@ -263,8 +294,20 @@ static void run(Arguments args) throws IOException {

fontRegistry.loadFontBundle("NotoSansDevanagari-Regular", "1", "Devanagari");

String outputName;
if (!overtureFile.isEmpty()) {
String filename = Path.of(overtureFile).getFileName().toString();
if (filename.endsWith(".parquet")) {
outputName = filename.substring(0, filename.length() - ".parquet".length());
} else {
outputName = filename;
}
} else {
outputName = area;
}

planetiler.setProfile(new Basemap(qrankDb, countryCoder, clip, layer))
.setOutput(Path.of(area + ".pmtiles"))
.setOutput(Path.of(outputName + ".pmtiles"))
.run();
}
}
Loading
Loading