-
-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Basic schema enhancements for Felt basemap #37
Changes from all commits
0920a06
3ea5211
17f8ddd
e4c53c6
a44c44d
0ed7b0c
c643234
1077301
53c8ac7
6825103
14d0824
3b55d6a
d8258ee
43eb247
53ce164
74d4578
347f121
0079233
e675da6
1e2b1c5
71c827a
4db8422
b22c1ea
8252e77
aeef7ac
f1858ae
5b62ac0
5401363
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,25 +12,35 @@ You will need [Java 17+](https://github.com/onthegomap/planetiler/blob/main/CONT | |
Generate and inspect a basemap PMTiles of any named area: | ||
|
||
1. Clone this repository. | ||
```sh | ||
|
||
```shell | ||
git clone [email protected]:protomaps/basemaps.git | ||
``` | ||
2. change to the `tiles` directory, download dependencies and compile the JAR: | ||
```sh | ||
|
||
```shell | ||
cd basemap/tiles | ||
mvn clean package | ||
``` | ||
3. Download and generate `monaco.pmtiles` in the current directory: | ||
``` | ||
|
||
```shell | ||
java -jar target/*-with-deps.jar --download --force --area=monaco | ||
``` | ||
|
||
4. Switch to the `compare/` directory to run the map compare tool: | ||
|
||
``` | ||
```shell | ||
cd compare | ||
npm run serve | ||
``` | ||
|
||
5. Linting to apply code formatting | ||
|
||
```shell | ||
mvn spotless:apply | ||
``` | ||
|
||
## License | ||
|
||
[BSD 3-clause](/LICENSE.md). The organization of layers and features used by these map styles, as well as the "look and feel" of the resulting maps, are licensed [CC0](https://creativecommons.org/publicdomain/zero/1.0/). However, maps using the [Protomaps web map service](https://protomaps.com) or another OpenStreetMap-based service will be subject to the terms of the [Open Database License](https://www.openstreetmap.org/copyright). |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -163,6 +163,19 @@ export function nolabels_layers(source: string, c: Theme): any[] { | |
"fill-color": c.water, | ||
}, | ||
}, | ||
{ | ||
bdon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
id: "landuse_pier", | ||
type: "fill", | ||
source: source, | ||
"source-layer": "landuse", | ||
filter: [ | ||
"any", | ||
["==", "man_made", "pier"], | ||
], | ||
paint: { | ||
"fill-color": c.earth, | ||
}, | ||
}, | ||
{ | ||
id: "roads_tunnels_other_casing", | ||
type: "line", | ||
|
@@ -534,6 +547,30 @@ export function nolabels_layers(source: string, c: Theme): any[] { | |
visibility: casingVisibility, | ||
}, | ||
}, | ||
{ | ||
id: "transit_pier", | ||
type: "line", | ||
source: source, | ||
"source-layer": "transit", | ||
filter: [ | ||
"any", | ||
["==", "pmap:kind", "pier"], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
], | ||
paint: { | ||
"line-color": c.minor, | ||
"line-width": [ | ||
"interpolate", | ||
["exponential", 1.6], | ||
["zoom"], | ||
12, | ||
0, | ||
12.5, | ||
0.5, | ||
20, | ||
16, | ||
], | ||
}, | ||
}, | ||
{ | ||
id: "roads_minor", | ||
type: "line", | ||
|
@@ -1142,6 +1179,23 @@ export function labels_layers(source: string, c: Theme): any[] { | |
"text-halo-width": 1.5, | ||
}, | ||
}, | ||
{ | ||
id: "pois", | ||
bdon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
type: "symbol", | ||
source: source, | ||
minzoom: 17, | ||
"source-layer": "pois", | ||
layout: { | ||
"text-font": ["NotoSans-Regular"], | ||
"text-field": ["get", "name"], | ||
"text-size": 12, | ||
}, | ||
paint: { | ||
"text-color": c.subplace_label, | ||
"text-halo-color": c.subplace_label_halo, | ||
"text-halo-width": 1.5, | ||
}, | ||
}, | ||
{ | ||
id: "places_subplace", | ||
type: "symbol", | ||
|
@@ -1187,10 +1241,16 @@ export function labels_layers(source: string, c: Theme): any[] { | |
"source-layer": "places", | ||
filter: ["==", "pmap:kind", "city"], | ||
layout: { | ||
"symbol-sort-key": ["number", ["get", "pmap:min_zoom"]], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
"text-field": "{name}", | ||
"text-font": ["NotoSans-Bold"], | ||
"text-size": ["step", ["get", "pmap:rank"], 0, 1, 12, 2, 10], | ||
"text-variable-anchor": ["bottom-left"], | ||
"text-anchor": { | ||
stops: [ | ||
[7, "left"], | ||
[8, "center"], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
], | ||
}, | ||
"text-radial-offset": 0.2, | ||
}, | ||
paint: { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,7 @@ public void processFeature(SourceFeature sf, FeatureCollector features) { | |
List<OsmReader.RelationMember<AdminRecord>> recs = sf.relationInfo(AdminRecord.class); | ||
if (recs.size() > 0) { | ||
OptionalInt minAdminLevel = recs.stream().mapToInt(r -> r.relation().adminLevel).min(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NOTE: This looks like it prevents the City and County of San Francisco from appearing as a locality boundary line, instead it only appears as a county boundary line. An odd case, but this is true for several other "global cities" in the USA and elsewhere, too. |
||
OptionalInt disputed = recs.stream().mapToInt(r -> r.relation().disputed).max(); | ||
var line = | ||
features.line(this.name()).setId(FeatureId.create(sf)).setMinPixelSize(0).setAttr("pmap:min_admin_level", | ||
minAdminLevel.getAsInt()); | ||
|
@@ -40,17 +41,24 @@ public void processFeature(SourceFeature sf, FeatureCollector features) { | |
} else { | ||
line.setMinZoom(10); | ||
} | ||
|
||
if (disputed.getAsInt() == 1) { | ||
line.setAttr("disputed", 1); | ||
} | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public List<OsmRelationInfo> preprocessOsmRelation(OsmElement.Relation relation) { | ||
if (relation.hasTag("type", "boundary") && relation.hasTag("boundary", "administrative")) { | ||
if (relation.hasTag("type", "boundary") && | ||
(relation.hasTag("boundary", "administrative") || relation.hasTag("boundary", "disputed"))) { | ||
Integer adminLevel = Parse.parseIntOrNull(relation.getString("admin_level")); | ||
Integer disputed = relation.hasTag("boundary", "disputed") ? 1 : 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO: This seems to always eval to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @nvkelso what relations/area are you testing on? on observation with Overpass Turbo it seems many relations with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Line of Control in Cyprus (r/13562322)is an odd ball – it's I was testing around Israel as the build there has a smaller bounding box than India or China and more
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems to evaluate to 1 on this relation: https://www.openstreetmap.org/relation/1703814 |
||
|
||
if (adminLevel == null || adminLevel > 8) | ||
return null; | ||
return List.of(new AdminRecord(relation.id(), adminLevel)); | ||
return List.of(new AdminRecord(relation.id(), adminLevel, disputed)); | ||
} | ||
return null; | ||
} | ||
|
@@ -64,5 +72,5 @@ public List<VectorTile.Feature> postProcess(int zoom, List<VectorTile.Feature> i | |
); | ||
} | ||
|
||
private record AdminRecord(long id, int adminLevel) implements OsmRelationInfo {} | ||
private record AdminRecord(long id, int adminLevel, int disputed) implements OsmRelationInfo {} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,8 +23,16 @@ public void processFeature(SourceFeature sf, FeatureCollector features) { | |
.setId(FeatureId.create(sf)) | ||
.setAttr("waterway", sf.getString("waterway")) | ||
.setAttr("natural", sf.getString("natural")) | ||
// Add less common attributes only at higher zooms | ||
.setAttrWithMinzoom("bridge", sf.getString("bridge"), 12) | ||
.setAttrWithMinzoom("tunnel", sf.getString("tunnel"), 12) | ||
.setAttrWithMinzoom("layer", sf.getString("layer"), 12) | ||
.setZoomRange(12, 15); | ||
|
||
if (sf.hasTag("intermittent", "yes")) { | ||
feat.setAttr("intermittent", 1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For way 316401077 in israel-and-palestine GeoFabrik: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bdon up to you if you want this to be a boolean in the MVT or an int There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tilezen uses a boolean so let's converge on that later |
||
} | ||
|
||
String kind = "other"; | ||
if (sf.hasTag("waterway")) { | ||
kind = "waterway"; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,8 +4,8 @@ | |
import com.onthegomap.planetiler.ForwardingProfile; | ||
import com.onthegomap.planetiler.VectorTile; | ||
import com.onthegomap.planetiler.reader.SourceFeature; | ||
import com.onthegomap.planetiler.util.Parse; | ||
import com.protomaps.basemap.feature.FeatureId; | ||
import com.protomaps.basemap.names.NeNames; | ||
import com.protomaps.basemap.names.OsmNames; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
@@ -17,10 +17,68 @@ public String name() { | |
return "places"; | ||
} | ||
|
||
public void processNe(SourceFeature sf, FeatureCollector features) { | ||
var sourceLayer = sf.getSourceLayer(); | ||
var kind = ""; | ||
var kind_detail = ""; | ||
|
||
var theme_min_zoom = 0; | ||
var theme_max_zoom = 0; | ||
if (sourceLayer.equals("ne_10m_populated_places")) { | ||
theme_min_zoom = 1; | ||
theme_max_zoom = 8; | ||
} | ||
|
||
// Test for props because of Natural Earth funk | ||
if (sf.isPoint() && sf.hasTag("featurecla") && sf.hasTag("min_zoom")) { | ||
switch (sf.getString("featurecla")) { | ||
case "Admin-0 capital": | ||
case "Admin-0 capital alt": | ||
case "Admin-0 region capital": | ||
kind = "city"; | ||
break; | ||
case "Admin-1 capital": | ||
case "Admin-1 region capital": | ||
kind = "city"; | ||
break; | ||
case "Populated place": | ||
kind = "city"; | ||
break; | ||
case "Historic place": | ||
kind = "locality"; | ||
kind_detail = "hamlet"; | ||
break; | ||
case "Scientific station": | ||
kind = "locality"; | ||
kind_detail = "scientific_station"; | ||
break; | ||
} | ||
} | ||
|
||
if (kind != "") { | ||
var feat = features.point(this.name()) | ||
.setAttr("name", sf.getString("name")) | ||
.setAttr("pmap:min_zoom", sf.getLong("min_zoom")) | ||
.setZoomRange( | ||
sf.getString("min_zoom") == null ? theme_min_zoom : (int) Double.parseDouble(sf.getString("min_zoom")), | ||
theme_max_zoom) | ||
.setAttr("pmap:kind", kind) | ||
.setAttr("pmap:kind_detail", kind_detail) | ||
.setAttr("population", sf.getString("pop_max")) | ||
.setAttr("population_rank", sf.getString("rank_max")) | ||
.setAttr("wikidata_id", sf.getString("wikidata")) | ||
.setBufferPixels(128); | ||
|
||
NeNames.setNeNames(feat, sf, 0); | ||
} | ||
} | ||
|
||
@Override | ||
public void processFeature(SourceFeature sf, FeatureCollector features) { | ||
if (sf.isPoint() && | ||
(sf.hasTag("place", "suburb", "town", "village", "neighbourhood", "city", "country", "state"))) { | ||
(sf.hasTag("place", "suburb", "town", "village", "neighbourhood", "city", "country", "state", "province"))) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We were missing |
||
Integer population = | ||
sf.getString("population") == null ? 0 : (int) Double.parseDouble(sf.getString("population")); | ||
var feat = features.point(this.name()) | ||
.setId(FeatureId.create(sf)) | ||
.setAttr("place", sf.getString("place")) | ||
|
@@ -31,38 +89,74 @@ public void processFeature(SourceFeature sf, FeatureCollector features) { | |
|
||
if (sf.hasTag("place", "country")) { | ||
feat.setAttr("pmap:kind", "country") | ||
.setZoomRange(0, 15); | ||
.setZoomRange(0, 9); | ||
bdon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} else if (sf.hasTag("place", "state", "province")) { | ||
feat.setAttr("pmap:kind", "state") | ||
.setZoomRange(4, 15); | ||
.setZoomRange(4, 11); | ||
bdon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} else if (sf.hasTag("place", "city")) { | ||
feat.setAttr("pmap:kind", "city") | ||
.setZoomRange(4, 15); | ||
|
||
if (sf.getString("population") != null) { | ||
Integer population = Parse.parseIntOrNull(sf.getString("population")); | ||
if (population != null) { | ||
feat.setAttr("population", population); | ||
feat.setSortKey((int) Math.log(population)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This moved farther down... |
||
// TODO: use label grid | ||
} else { | ||
feat.setSortKey(0); | ||
} | ||
} | ||
|
||
} else if (sf.hasTag("place", "suburb")) { | ||
feat.setAttr("pmap:kind", "neighbourhood") | ||
.setZoomRange(8, 15); | ||
if (population.equals(0)) { | ||
population = 10000; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here's where we start backfilling population by place type. |
||
} | ||
} else if (sf.hasTag("place", "town")) { | ||
feat.setAttr("pmap:kind", "neighbourhood") | ||
.setZoomRange(8, 15); | ||
if (population.equals(0)) { | ||
population = 5000; | ||
} | ||
} else if (sf.hasTag("place", "village")) { | ||
feat.setAttr("pmap:kind", "neighbourhood") | ||
.setZoomRange(10, 15); | ||
if (population.equals(0)) { | ||
population = 2000; | ||
} | ||
} else if (sf.hasTag("place", "suburb")) { | ||
feat.setAttr("pmap:kind", "neighbourhood") | ||
.setZoomRange(8, 15); | ||
} else { | ||
feat.setAttr("pmap:kind", "neighbourhood") | ||
.setZoomRange(12, 15); | ||
} | ||
|
||
if (population != null) { | ||
feat.setAttr("population", population); | ||
feat.setSortKey((int) Math.log(population)); | ||
// TODO: use label grid | ||
} else { | ||
feat.setSortKey(0); | ||
} | ||
|
||
int population_rank = 0; | ||
|
||
int[] pop_breaks = { | ||
1000000000, | ||
100000000, | ||
50000000, | ||
20000000, | ||
10000000, | ||
5000000, | ||
1000000, | ||
500000, | ||
200000, | ||
100000, | ||
50000, | ||
20000, | ||
10000, | ||
5000, | ||
2000, | ||
1000, | ||
200, | ||
0}; | ||
|
||
for (int i = 0; i < pop_breaks.length; i++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't working in Java, but works fine in Python. Help! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you want to it seems like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
if (population >= pop_breaks[i]) { | ||
population_rank = pop_breaks.length - i; | ||
break; | ||
} | ||
} | ||
|
||
feat.setAttr("population_rank", population_rank); | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When adding the new linting section, IntelliJ IDEA CE recommends
shell
notsh
so I updated the instances above, too.