Skip to content

Commit

Permalink
Parquet/no-build-tool java profile usability improvements (#914)
Browse files Browse the repository at this point in the history
  • Loading branch information
msbarry authored Jun 11, 2024
1 parent 7ca7531 commit bd5e527
Show file tree
Hide file tree
Showing 40 changed files with 1,924 additions and 502 deletions.
4 changes: 4 additions & 0 deletions planetiler-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.snakeyaml</groupId>
<artifactId>snakeyaml-engine</artifactId>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public Feature point(String layer) {
return geometry(layer, source.worldGeometry());
} catch (GeometryException e) {
e.log(stats, "feature_point", "Error getting point geometry for " + source);
return new Feature(layer, EMPTY_GEOM, source.id());
return empty(layer);
}
}

Expand All @@ -106,7 +106,7 @@ public Feature line(String layer) {
return geometry(layer, source.line());
} catch (GeometryException e) {
e.log(stats, "feature_line", "Error constructing line for " + source);
return new Feature(layer, EMPTY_GEOM, source.id());
return empty(layer);
}
}

Expand All @@ -126,7 +126,7 @@ public Feature partialLine(String layer, double start, double end) {
return geometry(layer, source.partialLine(start, end));
} catch (GeometryException e) {
e.log(stats, "feature_partial_line", "Error constructing partial line for " + source);
return new Feature(layer, EMPTY_GEOM, source.id());
return empty(layer);
}
}

Expand All @@ -146,10 +146,27 @@ public Feature polygon(String layer) {
return geometry(layer, source.polygon());
} catch (GeometryException e) {
e.log(stats, "feature_polygon", "Error constructing polygon for " + source);
return new Feature(layer, EMPTY_GEOM, source.id());
return empty(layer);
}
}

/**
* Starts building a new polygon, line, or point map feature based on the geometry type of the input feature.
*
* @param layer the output vector tile layer this feature will be written to
* @return a feature that can be configured further.
*/
public Feature anyGeometry(String layer) {
return source.canBePolygon() ? polygon(layer) :
source.canBeLine() ? line(layer) :
source.isPoint() ? point(layer) :
empty(layer);
}

private Feature empty(String layer) {
return new Feature(layer, EMPTY_GEOM, source.id());
}

/**
* Starts building a new point map feature with geometry from {@link Geometry#getCentroid()} of the source feature.
*
Expand All @@ -161,7 +178,7 @@ public Feature centroid(String layer) {
return geometry(layer, source.centroid());
} catch (GeometryException e) {
e.log(stats, "feature_centroid", "Error getting centroid for " + source);
return new Feature(layer, EMPTY_GEOM, source.id());
return empty(layer);
}
}

Expand All @@ -178,7 +195,7 @@ public Feature centroidIfConvex(String layer) {
return geometry(layer, source.centroidIfConvex());
} catch (GeometryException e) {
e.log(stats, "feature_centroid_if_convex", "Error constructing centroid if convex for " + source);
return new Feature(layer, EMPTY_GEOM, source.id());
return empty(layer);
}
}

Expand All @@ -194,7 +211,7 @@ public Feature pointOnSurface(String layer) {
return geometry(layer, source.pointOnSurface());
} catch (GeometryException e) {
e.log(stats, "feature_point_on_surface", "Error constructing point on surface for " + source);
return new Feature(layer, EMPTY_GEOM, source.id());
return empty(layer);
}
}

Expand All @@ -216,7 +233,7 @@ public Feature innermostPoint(String layer, double tolerance) {
return geometry(layer, source.innermostPoint(tolerance));
} catch (GeometryException e) {
e.log(stats, "feature_innermost_point", "Error constructing innermost point for " + source);
return new Feature(layer, EMPTY_GEOM, source.id());
return empty(layer);
}
}

Expand Down Expand Up @@ -297,6 +314,23 @@ default T inheritAttrFromSource(String key) {
return setAttr(key, collector().source.getTag(key));
}

/** Copies the values for {@code keys} attributes from source feature to the output feature. */
default T inheritAttrsFromSource(String... keys) {
for (var key : keys) {
inheritAttrFromSource(key);
}
return self();
}


/** Copies the values for {@code keys} attributes from source feature to the output feature. */
default T inheritAttrsFromSourceWithMinzoom(int minzoom, String... keys) {
for (var key : keys) {
setAttrWithMinzoom(key, collector().source.getTag(key), minzoom);
}
return self();
}

/**
* Sets an attribute on the output feature to either a string, number, boolean, or instance of {@link ZoomFunction}
* to change the value for {@code key} by zoom-level.
Expand All @@ -319,7 +353,7 @@ default T setAttrWithMinzoom(String key, Object value, int minzoom) {
* size.
*/
default T setAttrWithMinSize(String key, Object value, double minPixelSize) {
return setAttrWithMinzoom(key, value, collector().getMinZoomForPixelSize(minPixelSize));
return setAttrWithMinzoom(key, value, getMinZoomForPixelSize(minPixelSize));
}

/**
Expand All @@ -334,7 +368,11 @@ default T setAttrWithMinSize(String key, Object value, double minPixelSize) {
default T setAttrWithMinSize(String key, Object value, double minPixelSize, int minZoomIfBigEnough,
int minZoomToShowAlways) {
return setAttrWithMinzoom(key, value,
Math.clamp(collector().getMinZoomForPixelSize(minPixelSize), minZoomIfBigEnough, minZoomToShowAlways));
Math.clamp(getMinZoomForPixelSize(minPixelSize), minZoomIfBigEnough, minZoomToShowAlways));
}

default int getMinZoomForPixelSize(double minPixelSize) {
return collector().getMinZoomForPixelSize(minPixelSize);
}

/**
Expand Down Expand Up @@ -410,7 +448,7 @@ public final class Feature implements WithZoomRange<Feature>, WithAttrs<Feature>
private ZoomFunction<Number> labelGridPixelSize = null;
private ZoomFunction<Number> labelGridLimit = null;

private boolean attrsChangeByZoom = false;
private boolean mustUnwrapValues = false;
private CacheByZoom<Map<String, Object>> attrCache = null;
private CacheByZoom<List<RangeWithTags>> partialRangeCache = null;

Expand Down Expand Up @@ -817,18 +855,21 @@ private Map<String, Object> computeAttrsAtZoom(int zoom) {
}

private static Object unwrap(Object object, int zoom) {
if (object instanceof ZoomFunction<?> fn) {
object = fn.apply(zoom);
}
if (object instanceof Struct struct) {
object = struct.rawValue();
for (int i = 0; i < 100; i++) {
switch (object) {
case ZoomFunction<?> fn -> object = fn.apply(zoom);
case Struct struct -> object = struct.rawValue();
case null, default -> {
return object;
}
}
}
return object;
throw new IllegalStateException("Failed to unwrap at z" + zoom + ": " + object);
}

/** Returns the attribute to put on all output vector tile features at a zoom level. */
public Map<String, Object> getAttrsAtZoom(int zoom) {
if (!attrsChangeByZoom) {
if (!mustUnwrapValues) {
return attrs;
}
if (attrCache == null) {
Expand All @@ -840,8 +881,8 @@ public Map<String, Object> getAttrsAtZoom(int zoom) {

@Override
public Feature setAttr(String key, Object value) {
if (value instanceof ZoomFunction) {
attrsChangeByZoom = true;
if (value instanceof ZoomFunction || value instanceof Struct) {
mustUnwrapValues = true;
}
if (value != null) {
attrs.put(key, value);
Expand All @@ -852,8 +893,8 @@ public Feature setAttr(String key, Object value) {
@Override
public Feature putAttrs(Map<String, Object> attrs) {
for (Object value : attrs.values()) {
if (value instanceof ZoomFunction) {
attrsChangeByZoom = true;
if (value instanceof ZoomFunction || value instanceof Struct) {
mustUnwrapValues = true;
break;
}
}
Expand Down Expand Up @@ -957,7 +998,7 @@ Partial withAttr(String key, Object value) {
return new Partial(omit, MapUtil.with(attrs, key, value));
}
}
MergingRangeMap<Partial> result = MergingRangeMap.unit(new Partial(false, attrs), Partial::merge);
MergingRangeMap<Partial> result = MergingRangeMap.unit(new Partial(false, getAttrsAtZoom(zoom)), Partial::merge);
for (var override : partialOverrides) {
result.update(override.range(), m -> switch (override) {
case Attr attr -> m.withAttr(attr.key, unwrap(attr.value, zoom));
Expand Down Expand Up @@ -1018,6 +1059,9 @@ public LinearRange setMaxZoom(int max) {

@Override
public LinearRange setAttr(String key, Object value) {
if (value instanceof ZoomFunction<?> || value instanceof Struct) {
mustUnwrapValues = true;
}
return add(new Attr(range, key, value));
}

Expand Down Expand Up @@ -1049,6 +1093,12 @@ public LinearRange linearRange(Range<Double> range) {
return entireLine().linearRange(range);
}


@Override
public int getMinZoomForPixelSize(double minPixelSize) {
return WithAttrs.super.getMinZoomForPixelSize(minPixelSize / (range.upperEndpoint() - range.lowerEndpoint()));
}

@Override
public FeatureCollector collector() {
return FeatureCollector.this;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.onthegomap.planetiler;

import com.onthegomap.planetiler.reader.SourceFeature;

/**
* Subcomponent of {@link Profile} that handles processing layers from a feature, and optionally when that source is
* finished.
*/
@FunctionalInterface
public interface FeatureProcessor<T extends SourceFeature> {

/**
* Generates output features for any input feature that should appear in the map.
* <p>
* Multiple threads may invoke this method concurrently for a single data source so implementations should ensure
* thread-safe access to any shared data structures. Separate data sources are processed sequentially.
* <p>
* All OSM nodes are processed first, then ways, then relations.
*
* @param sourceFeature the input feature from a source dataset (OSM element, shapefile element, etc.)
* @param features a collector for generating output map features to emit
*/
void processFeature(T sourceFeature, FeatureCollector features);
}
Loading

0 comments on commit bd5e527

Please sign in to comment.