planetiler/planetiler-core/src/main/java/com/onthegomap/planetiler/util/ZoomFunction.java

92 wiersze
3.1 KiB
Java
Czysty Zwykły widok Historia

package com.onthegomap.planetiler.util;
2021-05-13 10:25:06 +00:00
import com.onthegomap.planetiler.geo.GeoUtils;
2021-05-13 10:25:06 +00:00
import java.util.Map;
import java.util.TreeMap;
import java.util.function.IntFunction;
2021-09-10 00:46:20 +00:00
/**
* A value that changes by zoom level.
* <p>
* {@link #apply(int)} returns the value at the zoom level.
*/
2021-05-13 10:25:06 +00:00
public interface ZoomFunction<T> extends IntFunction<T> {
2021-10-20 01:57:47 +00:00
/** Returns {@code value} when {@code zom >= min}, and null otherwise. */
2021-05-13 10:25:06 +00:00
static <T> ZoomFunction<T> minZoom(int min, T value) {
return zoom -> zoom >= min ? value : null;
}
2021-09-10 00:46:20 +00:00
/** Returns {@code value} when zoom is between min and max inclusive, null otherwise. */
2021-05-13 10:25:06 +00:00
static <T> ZoomFunction<T> zoomRange(int min, int max, T value) {
return zoom -> zoom >= min && zoom <= max ? value : null;
}
2021-10-20 01:57:47 +00:00
/** Returns {@code value} when {@code zoom <= max}, and null otherwise. */
2021-05-13 10:25:06 +00:00
static <T> ZoomFunction<T> maxZoom(int max, T value) {
return zoom -> zoom <= max ? value : null;
}
2021-09-10 00:46:20 +00:00
/** Invoke a function at a zoom level and returns {@code defaultValue} if the function or result were null. */
2021-05-13 10:25:06 +00:00
static double applyAsDoubleOrElse(ZoomFunction<? extends Number> fn, int zoom, double defaultValue) {
if (fn == null) {
return defaultValue;
}
Number result = fn.apply(zoom);
return result == null ? defaultValue : result.doubleValue();
}
2021-09-10 00:46:20 +00:00
/** Invoke a function at a zoom level and returns {@code defaultValue} if the function or result were null. */
2021-05-13 10:25:06 +00:00
static int applyAsIntOrElse(ZoomFunction<? extends Number> fn, int zoom, int defaultValue) {
if (fn == null) {
return defaultValue;
}
Number result = fn.apply(zoom);
return result == null ? defaultValue : result.intValue();
}
2021-09-10 00:46:20 +00:00
/**
* Returns a zoom function that returns the value from the next higher key in {@code thresholds} or {@code null} if
* over the max key.
*/
2021-05-13 10:25:06 +00:00
static <T> ZoomFunction<T> fromMaxZoomThresholds(Map<Integer, ? extends T> thresholds) {
return fromMaxZoomThresholds(thresholds, null);
}
2021-09-10 00:46:20 +00:00
/**
* Returns a zoom function that returns the value from the next higher key in {@code thresholds} or {@code
* defaultValue}.
*/
2021-05-13 10:25:06 +00:00
static <T> ZoomFunction<T> fromMaxZoomThresholds(Map<Integer, ? extends T> thresholds, T defaultValue) {
TreeMap<Integer, T> orderedMap = new TreeMap<>(thresholds);
orderedMap.put(Integer.MAX_VALUE, defaultValue);
return zoom -> orderedMap.ceilingEntry(zoom).getValue();
}
2021-09-10 00:46:20 +00:00
/**
* A zoom function that lets you set the value to return for a zoom level in meters and when called, it returns how
2021-09-10 00:46:20 +00:00
* many pixels long that number of meters is at the equator.
*/
class MeterToPixelThresholds implements ZoomFunction<Number> {
2021-06-19 09:35:57 +00:00
private final TreeMap<Integer, Number> levels = new TreeMap<>();
2021-06-19 09:35:57 +00:00
private MeterToPixelThresholds() {}
2021-09-10 00:46:20 +00:00
/** Sets the value to return at {@code zoom} in meters. */
public MeterToPixelThresholds put(int zoom, double meters) {
2021-06-19 09:35:57 +00:00
levels.put(zoom, GeoUtils.metersToPixelAtEquator(zoom, meters));
return this;
}
@Override
public Number apply(int value) {
return levels.get(value);
}
2021-05-13 10:25:06 +00:00
}
2021-09-10 00:46:20 +00:00
static MeterToPixelThresholds meterThresholds() {
return new MeterToPixelThresholds();
2021-05-13 10:25:06 +00:00
}
}