Encode OSM node/way/relation in vector tile feature id (#826)

pull/943/head
Michael Barry 2024-06-28 07:00:56 -04:00 zatwierdzone przez GitHub
rodzic 07afc77fbb
commit db0eb8afb8
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
9 zmienionych plików z 79 dodań i 14 usunięć

Wyświetl plik

@ -64,7 +64,11 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
* @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;
}

Wyświetl plik

@ -445,7 +445,11 @@ public class Arguments {
*/
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;
}

Wyświetl plik

@ -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;
@ -213,7 +214,11 @@ public record PlanetilerConfig(
"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)
);
}

Wyświetl plik

@ -320,6 +320,10 @@ public abstract class SourceFeature implements WithTags, WithGeometryType {
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() {

Wyświetl plik

@ -27,6 +27,7 @@ public interface OsmElement extends WithTags {
Type type();
enum Type {
OTHER,
NODE,
WAY,
RELATION
@ -46,7 +47,7 @@ public interface OsmElement extends WithTags {
@Override
public Type type() {
return null;
return Type.OTHER;
}
}

Wyświetl plik

@ -644,6 +644,16 @@ public class OsmReader implements Closeable, MemoryEstimator.HasEstimate {
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()));

Wyświetl plik

@ -942,7 +942,7 @@ class PlanetilerTests {
feature(newPoint(128, 128), Map.of(
"attr", "value",
"name", "name value"
))
), 11)
)
), results.tiles);
}
@ -1031,7 +1031,7 @@ class PlanetilerTests {
feature(newLineString(128, 128, 192, 192), Map.of(
"attr", "value",
"name", "name value"
))
), 32)
)
), results.tiles);
}
@ -1157,7 +1157,7 @@ class PlanetilerTests {
"attr", "value",
"name", "name value",
"relname", "rel name"
))
), 173)
)
), results.tiles);
}
@ -1219,20 +1219,21 @@ class PlanetilerTests {
@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);
}
}

Wyświetl plik

@ -284,7 +284,9 @@ public class TestUtils {
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;
@ -490,12 +492,21 @@ public class TestUtils {
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)));
@ -507,12 +518,25 @@ public class TestUtils {
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);
}

Wyświetl plik

@ -363,4 +363,16 @@ class ArgumentsTest {
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));
}
}