-
-
Notifications
You must be signed in to change notification settings - Fork 44
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
Round 2 enhancements for Felt #47
Changes from 37 commits
2ecc9fc
4646d8f
bdcd8c1
0e45322
99bd2df
3a8ad37
bda1226
cce8016
39e9092
a33723f
330ad89
dedcc61
d452bbe
0faa99d
d6baab1
89cc47c
f19aa7d
e501a32
1a34443
73249f6
44f3cc2
a93e7b1
dde2a3f
1dce93b
492e03c
05c7890
492919e
29839e6
1b91f74
153a6bd
fe8aa5a
dc6b9c1
bffdf4d
ba46ffe
55c1dbf
c73c1df
30ab35c
28a99c8
99a4c73
b56aafa
62cb079
79be151
45c11fc
59d4995
f1b9478
78a6c78
6a9972c
553e5eb
2c7ab10
4d6e41e
433d6c2
88fb01c
fa265a0
b27b857
34ca7b3
b5a5b99
27291b4
22b7635
e18abdf
e0a56da
84ddc13
eed7401
19c529c
9fb4d01
06fe05c
b46e565
e68bd09
5fbd2a2
4581fc1
d94aafb
41256f1
580d998
ce14bef
7739f7f
d95ab78
02da19c
8b69a55
36d1527
3d06817
7babaad
3c1789d
90f584b
49e81d4
262e9ec
5b0ae4e
b7221a2
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 |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# download dependencies and compile the JAR | ||
# generally do this after each code change | ||
clean: | ||
mvn clean package | ||
|
||
# is a build only partially finishes, the PMTiles can be corrupted | ||
clean-pmtiles: | ||
rm -rf *.pmtiles | ||
|
||
# This is optimized for local dev serving PMTiles out of directory local to this Makefile | ||
# Don't use this for production (instead set --cors=ORIGIN) | ||
# The default port is: 8080 (use --port to override) | ||
# Assumes go-pmtiles has been installed locally (eg prebuilt go binary download) & the path is added to your shell env | ||
# https://github.com/protomaps/go-pmtiles | ||
# Example tile coord to test with: http://localhost:8080/monaco/12/2133/1495.mvt | ||
serve: | ||
~/Downloads/pmtiles serve --cors=* . | ||
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 path should be updated... |
||
|
||
# | ||
# Testing areas | ||
# | ||
|
||
# Smallest | ||
# | ||
#Download and generate monaco.pmtiles in the current directory: | ||
monaco: | ||
bdon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
java -jar target/*-with-deps.jar --download --force --area=monaco | ||
|
||
# Generate monaco.pmtiles in the current directory (using already downloaded asset) | ||
monaco-fast: | ||
java -jar target/*-with-deps.jar --force --area=monaco | ||
|
||
# Medium | ||
# | ||
#Download and generate switzerland.pmtiles in the current directory: | ||
switzerland: | ||
java -jar target/*-with-deps.jar --download --force --area=switzerland | ||
|
||
# Generate switzerland.pmtiles in the current directory (using already downloaded asset) | ||
switzerland-fast: | ||
java -jar target/*-with-deps.jar --force --area=switzerland | ||
|
||
#Download and generate switzerland.pmtiles in the current directory: | ||
washington: | ||
java -jar target/*-with-deps.jar --download --force --area=washington | ||
|
||
# Generate switzerland.pmtiles in the current directory (using already downloaded asset) | ||
washington-fast: | ||
java -jar target/*-with-deps.jar --force --area=washington | ||
|
||
# Large | ||
# | ||
# Download and generate ca/california.pmtiles in the current directory: | ||
# Note: the slash confuses some downstream processes, try a symlink to california | ||
california: | ||
java -jar target/*-with-deps.jar --download --force --area=us/california | ||
|
||
# Generate ca/california.pmtiles in the current directory (using already downloaded asset) | ||
# Note: the slash confuses some downstream processes, try a symlink to california | ||
california-fast: | ||
java -jar target/*-with-deps.jar --force --area=us/california |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
import com.onthegomap.planetiler.VectorTile; | ||
import com.onthegomap.planetiler.geo.GeometryException; | ||
import com.onthegomap.planetiler.reader.SourceFeature; | ||
import com.onthegomap.planetiler.util.Exceptions; | ||
import com.protomaps.basemap.feature.FeatureId; | ||
import com.protomaps.basemap.names.OsmNames; | ||
import com.protomaps.basemap.postprocess.Area; | ||
|
@@ -20,10 +21,33 @@ public String name() { | |
return "buildings"; | ||
} | ||
|
||
static int quantize_val(double val, int step) { | ||
// special case: if val is very small, we don't want it rounding to zero, so | ||
// round the smallest values up to the first step. | ||
if( val < step ) { | ||
return (int) step; | ||
} | ||
|
||
return (int) Math.round(val / step) * step; | ||
} | ||
|
||
@Override | ||
public void processFeature(SourceFeature sf, FeatureCollector features) { | ||
if (sf.canBePolygon() && (sf.hasTag("building") || sf.hasTag("building:part"))) { | ||
if (sf.canBePolygon() && ( | ||
( sf.hasTag("building") && !sf.hasTag("building", "no")) || | ||
bdon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
( sf.hasTag("building:part") && !sf.hasTag("building:part", "no")))) | ||
{ | ||
Double height = parseDoubleOrNull(sf.getString("height")); | ||
Double min_height = parseDoubleOrNull(sf.getString("min_height")); | ||
bdon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Integer min_zoom = 11; | ||
String kind = "building"; | ||
|
||
// Limit building:part features to later zooms | ||
// TODO: (nvkelso 20230621) this should be based on area and volume, too | ||
if( sf.hasTag("building:part") ) { | ||
kind = "building_part"; | ||
min_zoom = 14; | ||
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. Building parts aren't useful to show until alter zooms when they become large enough on the map to discern. 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. +1 to making this based on area - think this should be expressible in pixels (planetiler considers a tile to be 256x256 onthegomap/planetiler#487 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 take back what I said, because at this step in the code we're not dealing with a specific zoom level. Overall code-wise, it bugs me a little to have so much logic down in postProcess. I would prefer postProcess be "operations that happen tile-wide", but it's now more like "operations that depend on zoom level". there isn't a solid way to assign different values like height quantization before that, though. I think we should keep it as is and I can refactor it into a well-tested postProcessor that handles both area filtering as well as height quantization per zoom-level. |
||
} | ||
|
||
if (height == null) { | ||
Double levels = parseDoubleOrNull(sf.getString("building:levels")); | ||
|
@@ -34,12 +58,21 @@ public void processFeature(SourceFeature sf, FeatureCollector features) { | |
|
||
var feature = features.polygon(this.name()) | ||
.setId(FeatureId.create(sf)) | ||
.setAttrWithMinzoom("building:part", sf.getString("building:part"), 13) | ||
.setAttr("pmap:kind", kind) | ||
.setAttrWithMinzoom("layer", sf.getString("layer"), 13) | ||
.setAttrWithMinzoom("height", height, 13) | ||
.setZoomRange(10, 15); | ||
// NOTE: Height is quantized by zoom in a post-process step | ||
.setAttr("height", height) | ||
.setZoomRange(min_zoom, 15); | ||
|
||
if( kind == "building_part") { | ||
// We don't need to set WithMinzoom because that's implicate with the ZoomRange | ||
feature.setAttr("pmap:kind_detail", sf.getString("building:part")); | ||
feature.setAttr("min_height", sf.getString("min_height")); | ||
} | ||
|
||
OsmNames.setOsmNames(feature, sf, 13); | ||
// Names should mostly just be for POIs | ||
// Sometimes building name and address are useful items, but only at zoom 17+ | ||
//OsmNames.setOsmNames(feature, sf, 13); | ||
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. Drop the names from buildings... if it's really important it'll show up in the POIs layer. Alternatively we could only set this starting at zoom 15? As some building names will be lost (when there isn't a business there). 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. Could non-building names become another POI kind? Are polygon geometries with a text property even labeled in a satisfying way using the MapLibre symbol layer? |
||
} | ||
} | ||
|
||
|
@@ -50,8 +83,62 @@ public List<VectorTile.Feature> postProcess(int zoom, List<VectorTile.Feature> i | |
} | ||
items = Area.filterArea(items, 0); | ||
|
||
if (zoom >= 14) | ||
// DEBUG | ||
//items = Area.addAreaTag(items); | ||
|
||
if (zoom >= 15) | ||
return items; | ||
|
||
// quantize height by zoom when less than max_zoom 15 to facilitate better feature merging | ||
bdon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for (var item : items) { | ||
try { | ||
if (item.attrs().containsKey("height")) { | ||
var height = (double) item.attrs().get("height"); | ||
|
||
// Protected against NULL values | ||
if( height > 0 ) { | ||
// at zoom <= 12 round height to nearest 20 meters | ||
if (zoom <= 12) { | ||
height = quantize_val(height, 20); | ||
} else | ||
// at zoom 13 round height to nearest 10 meters | ||
if (zoom == 13) { | ||
height = quantize_val(height, 10); | ||
} else | ||
// at zoom 14 round height to nearest 5 meters | ||
if (zoom == 14) { | ||
height = quantize_val(height, 5); | ||
} | ||
|
||
item.attrs().put("height", height); | ||
} | ||
} | ||
} catch( Exception e ) { } | ||
|
||
try { | ||
if (item.attrs().containsKey("min_height")) { | ||
var min_height = (double) item.attrs().get("min_height"); | ||
|
||
// Protected against NULL values | ||
if (min_height > 0) { | ||
if (zoom <= 12) { | ||
min_height = quantize_val(min_height, 20); | ||
} else | ||
// at zoom 13 round height to nearest 10 meters | ||
if (zoom == 13) { | ||
min_height = quantize_val(min_height, 10); | ||
} else | ||
// at zoom 14 round height to nearest 5 meters | ||
if (zoom == 14) { | ||
min_height = quantize_val(min_height, 5); | ||
} | ||
|
||
item.attrs().put("min_height", min_height); | ||
} | ||
} | ||
} catch( Exception e ) { } | ||
} | ||
|
||
return FeatureMerge.mergeNearbyPolygons(items, 3.125, 3.125, 0.5, 0.5); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,17 +17,18 @@ public String name() { | |
|
||
public void processOsm(SourceFeature sf, FeatureCollector features) { | ||
features.polygon(this.name()) | ||
.setZoomRange(6, 15).setBufferPixels(8); | ||
.setAttr("pmap:kind", "earth") | ||
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 is superfluous but nice to have in prep for v4 spec so each feature has a kind. They get merged, so very small file size hit. |
||
.setZoomRange(6, 15).setBufferPixels(8); | ||
} | ||
|
||
public void processNe(SourceFeature sf, FeatureCollector features) { | ||
var sourceLayer = sf.getSourceLayer(); | ||
if (sourceLayer.equals("ne_110m_land")) { | ||
features.polygon(this.name()).setZoomRange(0, 1); | ||
features.polygon(this.name()).setZoomRange(0, 1).setBufferPixels(8).setAttr("pmap:kind", "earth"); | ||
} else if (sourceLayer.equals("ne_50m_land")) { | ||
features.polygon(this.name()).setZoomRange(2, 4); | ||
features.polygon(this.name()).setZoomRange(2, 4).setBufferPixels(8).setAttr("pmap:kind", "earth"); | ||
} else if (sourceLayer.equals("ne_10m_land")) { | ||
features.polygon(this.name()).setZoomRange(5, 5); | ||
features.polygon(this.name()).setZoomRange(5, 5).setBufferPixels(8).setAttr("pmap:kind", "earth"); | ||
} | ||
} | ||
|
||
|
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.
New Makefile with easier to type commands...