Skip to content

Commit

Permalink
Encode OSM node/way/relation in vector tile feature id (#826)
Browse files Browse the repository at this point in the history
  • Loading branch information
msbarry authored Jun 28, 2024
1 parent 07afc77 commit db0eb8a
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ public Iterator<Feature> iterator() {
* @return a feature that can be configured further.
*/
public Feature geometry(String layer, Geometry geometry) {
Feature feature = new Feature(layer, geometry, source.id());
// TODO args could also provide a list of source IDs to put into slot 4, 5, 6, etc..
// to differentiate between other sources besides just OSM and "other"
long vectorTileId = config.featureSourceIdMultiplier() < 4 ? source.id() :
source.vectorTileFeatureId(config.featureSourceIdMultiplier());
Feature feature = new Feature(layer, geometry, vectorTileId);
output.add(feature);
return feature;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,11 @@ public Stats getStats() {
*/
public int getInteger(String key, String description, int defaultValue) {
String value = getArg(key, Integer.toString(defaultValue));
int parsed = Integer.parseInt(value);
int parsed = switch (value.toLowerCase(Locale.ROOT)) {
case "false" -> 0;
case "true" -> defaultValue;
default -> Integer.parseInt(value);
};
logArgValue(key, description, parsed);
return parsed;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ public record PlanetilerConfig(
Path tmpDir,
Path tileWeights,
double maxPointBuffer,
boolean logJtsExceptions
boolean logJtsExceptions,
int featureSourceIdMultiplier
) {

public static final int MIN_MINZOOM = 0;
Expand Down Expand Up @@ -213,7 +214,11 @@ public static PlanetilerConfig from(Arguments arguments) {
"clients that handle label collisions across tiles (most web and native clients). NOTE: Do not reduce if you need to support " +
"raster tile rendering",
Double.POSITIVE_INFINITY),
arguments.getBoolean("log_jts_exceptions", "Emit verbose details to debug JTS geometry errors", false)
arguments.getBoolean("log_jts_exceptions", "Emit verbose details to debug JTS geometry errors", false),
arguments.getInteger("feature_source_id_multiplier",
"Set vector tile feature IDs to (featureId * thisValue) + sourceId " +
"where sourceId is 1 for OSM nodes, 2 for ways, 3 for relations, and 0 for other sources. Set to false to disable.",
10)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,10 @@ public final long id() {
return id;
}

/** By default, the feature id is taken as-is from the input data source id. */
public long vectorTileFeatureId(int multiplier) {
return multiplier * id;
}

/** Returns true if this element has any OSM relation info. */
public boolean hasRelationInfo() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public interface OsmElement extends WithTags {
Type type();

enum Type {
OTHER,
NODE,
WAY,
RELATION
Expand All @@ -46,7 +47,7 @@ public int cost() {

@Override
public Type type() {
return null;
return Type.OTHER;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,16 @@ public OsmFeature(OsmElement elem, boolean point, boolean line, boolean polygon,
this.polygon = polygon;
}

@Override
public long vectorTileFeatureId(int multiplier) {
return (id() * multiplier) + switch (originalElement.type()) {
case OTHER -> 0;
case NODE -> 1;
case WAY -> 2;
case RELATION -> 3;
};
}

@Override
public Geometry latLonGeometry() throws GeometryException {
return latLonGeom != null ? latLonGeom : (latLonGeom = GeoUtils.worldToLatLonCoords(worldGeometry()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -942,7 +942,7 @@ void testOsmPoint() throws Exception {
feature(newPoint(128, 128), Map.of(
"attr", "value",
"name", "name value"
))
), 11)
)
), results.tiles);
}
Expand Down Expand Up @@ -1031,7 +1031,7 @@ void testOsmLine() throws Exception {
feature(newLineString(128, 128, 192, 192), Map.of(
"attr", "value",
"name", "name value"
))
), 32)
)
), results.tiles);
}
Expand Down Expand Up @@ -1157,7 +1157,7 @@ record TestRelationInfo(long id, String name) implements OsmRelationInfo {}
"attr", "value",
"name", "name value",
"relname", "rel name"
))
), 173)
)
), results.tiles);
}
Expand Down Expand Up @@ -1219,20 +1219,21 @@ record TestRelationInfo(long id, String name) implements OsmRelationInfo {}

@Test
void testPreprocessOsmNodesAndWays() throws Exception {
Set<Long> nodes1 = new HashSet<>();
HashMap<Long, Long> nodes1 = new HashMap<>();
Set<Long> nodes2 = new HashSet<>();
var profile = new Profile.NullProfile() {
@Override
public void preprocessOsmNode(OsmElement.Node node) {
if (node.hasTag("a", "b")) {
nodes1.add(node.id());
nodes1.put(node.id(), node.id());
}
}

@Override
public void preprocessOsmWay(OsmElement.Way way) {
if (nodes1.contains(way.nodes().get(0))) {
nodes2.add(way.nodes().get(0));
Long featureId = nodes1.get(way.nodes().get(0));
if (featureId != null) {
nodes2.add(featureId);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,9 @@ public static Map<TileCoord, List<ComparableFeature>> getTileMap(ReadableTileArc
case UNKNOWN -> throw new IllegalArgumentException("cannot decompress \"UNKNOWN\"");
};
var decoded = VectorTile.decode(bytes).stream()
.map(feature -> feature(decodeSilently(feature.geometry()), feature.layer(), feature.tags())).toList();
.map(
feature -> feature(decodeSilently(feature.geometry()), feature.layer(), feature.tags(), feature.id()))
.toList();
tiles.put(tile.coord(), decoded);
}
return tiles;
Expand Down Expand Up @@ -490,12 +492,21 @@ public int hashCode() {
public record ComparableFeature(
GeometryComparision geometry,
String layer,
Map<String, Object> attrs
Map<String, Object> attrs,
Long id
) {
ComparableFeature(
GeometryComparision geometry,
String layer,
Map<String, Object> attrs
) {
this(geometry, layer, attrs, null);
}

@Override
public boolean equals(Object o) {
return o == this || (o instanceof ComparableFeature other &&
(id == null || other.id == null || id.equals(other.id)) &&
geometry.equals(other.geometry) &&
attrs.equals(other.attrs) &&
(layer == null || other.layer == null || Objects.equals(layer, other.layer)));
Expand All @@ -507,12 +518,25 @@ public int hashCode() {
result = 31 * result + attrs.hashCode();
return result;
}

ComparableFeature withId(long id) {
return new ComparableFeature(geometry, layer, attrs, id);
}
}


public static ComparableFeature feature(Geometry geom, String layer, Map<String, Object> attrs, long id) {
return new ComparableFeature(new NormGeometry(geom), layer, attrs, id);
}

public static ComparableFeature feature(Geometry geom, String layer, Map<String, Object> attrs) {
return new ComparableFeature(new NormGeometry(geom), layer, attrs);
}

public static ComparableFeature feature(Geometry geom, Map<String, Object> attrs, long id) {
return new ComparableFeature(new NormGeometry(geom), null, attrs, id);
}

public static ComparableFeature feature(Geometry geom, Map<String, Object> attrs) {
return new ComparableFeature(new NormGeometry(geom), null, attrs);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,4 +363,16 @@ void testSubset() {
assertEquals("val_1", args.getArg("key-1"));
assertNull(args.getArg("key-3"));
}

@Test
void testFalseForInt() {
var args = Arguments.of(Map.of(
"true", "true",
"false", "false",
"3", "3"
));
assertEquals(1, args.getInteger("true", "", 1));
assertEquals(0, args.getInteger("false", "", 1));
assertEquals(3, args.getInteger("3", "", 1));
}
}

0 comments on commit db0eb8a

Please sign in to comment.