planetiler
planetiler copied to clipboard
[FEATURE] Include node/way/relation in the feature ID
Is your feature request related to a problem? Please describe.
As far as I can tell, for OpenStreetMap features, Planetiler uses the OSM ID for the MVT feature ID. However, it doesn't say whether it's a node, way, or relation, which is a problem because the IDs are not unique between those, i.e. there can be both a node #1000 and a way #1000.
Describe the solution you'd like I'd like to have some kind of encoding in the feature ID to describe the source of the ID--OSM node, OSM way, Natural Earth, etc. This could be done, for example, using the lower 3 bits of the ID.
Describe alternatives you've considered
I tried patching the OpenMapTiles schema repo to include the OSM ID with type in a tag, but this incurs a heavy tile size increase (around 10% on the small extract I tried) because they're all mostly different.
I'll write what I've learned so far while troubleshooting #215 in regards to IDs , @msbarry will hopefully correct my mistakes and give some further feedback:
- all IDs in the result (i.e. .mbtiles file) are allocated with
AtomicLong idGenerator
(callingincrementAndGet()
) - how that relates to your feature request: AFAIK source IDs usually do not make it into the result
- one exception I've stumbled upon so far: Natural Earth features should have
ne_id
tag thanks to https://github.com/onthegomap/planetiler/blob/main/planetiler-core/src/main/java/com/onthegomap/planetiler/reader/NaturalEarthReader.java#L172
- one exception I've stumbled upon so far: Natural Earth features should have
- how that relates to #215:
idGenerator
is (also) called in multi-threaded stages, hence we're getting different IDs if generating same desired result twice from same source data - TL;DR: if we solve this in a certain way (maintaining source IDs, etc.), it should also help with #215
We can expose a setId
method on Feature
, alongside the existing getSourceId
. That would provide a Profile-facing API to set the MVT id, but to make it useful we would also need to:
-
Expose whether something is an OSM node, way or relation through
SourceFeature
. We could assume points are nodes, and have a binaryisRelation
to distinguish polygons coming from ways or relations, but that would exclude cases where we might would to generate a Point geometry for a polygon label, or generate a centerline Line for a polygon label. -
Store the OSM type as part of the 64-bit long. What I usually do is only use the bottom 53 bits of the long; we'd need 2 bits (bits 51-52) to encode the enum:
NOT_OSM
,NODE
,WAY
,RELATION
and the rest of the lower bits for the source ID. Using only 53 bits means working in JavaScript is easier. But this feels too specific and can be handled on the Profile side instead of being defaulted in planetiler-core. -
If we want to track not only
NOT_OSM
but the specific Source, we would need some consistent ordering of Sources; Right now it seems like the main way to address a specific Source is by name e.g.osm
, but if there was a stable integer index for each Source the profile'ssetId
could use that to encode those into high bytes as well. (This could also be done by having a singleton mappingsourceName
to an ID in the profile but that seems messy)
#514 should be all that is needed for setting sourceID (not sure about tile features yet); the actual construction of a feature ID from OSM IDs can be something like the below (not tested heavily):
long tile_feature_id;
if (sourceFeature instanceof OsmSourceFeature osmFeature) {
var element = osmFeature.originalElement();
tile_feature_id = element.id();
long elem_type;
if (element instanceof OsmElement.Relation) {
elem_type = 0x3;
} else if (element instanceof OsmElement.Way) {
elem_type = 0x2;
} else { // is node
elem_type = 0x1;
}
tile_feature_id |= (elem_type << 51);
features.point("toilets").setSourceId(tile_feature_id);
}
With the addition of setId
on FeatureCollector
I think this issue can be closed on planetiler-core - the specific format of integer feature IDs is left up to the specific profile.
The default vector tile feature IDs should default to OSM IDs now, but with no distinguishing of nodes/ways/relations.