make min pixel size/tolerance configurable

pull/1/head
Mike Barry 2021-05-23 12:42:27 -04:00
rodzic c4ffc10b72
commit b2a6d5910e
4 zmienionych plików z 163 dodań i 14 usunięć

Wyświetl plik

@ -63,11 +63,15 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
private double defaultBufferPixels = 4;
private ZoomFunction<Number> bufferPixelOverrides;
private double defaultMinPixelSize = 1;
private double minPixelSizeAtMaxZoom = 256d / 4096;
private ZoomFunction<Number> minPixelSize = null;
private ZoomFunction<Number> labelGridPixelSize = null;
private ZoomFunction<Number> labelGridLimit = null;
private boolean attrsChangeByZoom = false;
private CacheByZoom<Map<String, Object>> attrCache = null;
private double defaultPixelTolerance = 0.1d;
private double pixelToleranceAtMaxZoom = 256d / 4096;
private ZoomFunction<Double> pixelTolerance = null;
private Feature(String layer, Geometry geom, boolean area) {
this.layer = layer;
@ -130,7 +134,8 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
}
public double getMinPixelSize(int zoom) {
return ZoomFunction.applyAsDoubleOrElse(minPixelSize, zoom, defaultMinPixelSize);
return zoom == 14 ? minPixelSizeAtMaxZoom
: ZoomFunction.applyAsDoubleOrElse(minPixelSize, zoom, defaultMinPixelSize);
}
public Feature setMinPixelSize(double minPixelSize) {
@ -143,6 +148,41 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
return this;
}
public Feature setMinPixelSizeAtMaxZoom(double minPixelSize) {
this.minPixelSizeAtMaxZoom = minPixelSize;
return this;
}
public Feature setMinPixelSizeAtAllZooms(int minPixelSize) {
return setMinPixelSizeAtMaxZoom(minPixelSize)
.setMinPixelSize(minPixelSize);
}
public Feature setPixelTolerance(double tolerance) {
this.defaultPixelTolerance = tolerance;
return this;
}
public Feature setPixelToleranceAtMaxZoom(double tolerance) {
this.pixelToleranceAtMaxZoom = tolerance;
return this;
}
public Feature setPixelToleranceAtAllZooms(double tolerance) {
return setPixelToleranceAtMaxZoom(tolerance).setPixelTolerance(tolerance);
}
public Feature setPixelToleranceBelowZoom(int zoom, double tolerance) {
this.pixelTolerance = ZoomFunction.maxZoom(zoom, tolerance);
return this;
}
public double getPixelTolerance(int zoom) {
return zoom == 14 ? pixelToleranceAtMaxZoom
: ZoomFunction.applyAsDoubleOrElse(pixelTolerance, zoom, defaultPixelTolerance);
}
public double getLabelGridPixelSizeAtZoom(int zoom) {
return ZoomFunction.applyAsDoubleOrElse(labelGridPixelSize, zoom, DEFAULT_LABEL_GRID_SIZE);
}

Wyświetl plik

@ -7,11 +7,9 @@ import com.onthegomap.flatmap.VectorTileEncoder;
import com.onthegomap.flatmap.geo.GeoUtils;
import com.onthegomap.flatmap.geo.GeometryException;
import com.onthegomap.flatmap.geo.TileCoord;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
import org.locationtech.jts.geom.Coordinate;
@ -84,7 +82,6 @@ public class FeatureRenderer {
long id = idGen.incrementAndGet();
boolean hasLabelGrid = feature.hasLabelGrid();
for (int zoom = feature.getMaxZoom(); zoom >= feature.getMinZoom(); zoom--) {
Map<TileCoord, Set<Coordinate>> sliced = new HashMap<>();
Map<String, Object> attrs = feature.getAttrsAtZoom(zoom);
double buffer = feature.getBufferPixelsAtZoom(zoom) / 256;
int tilesAtZoom = 1 << zoom;
@ -138,18 +135,12 @@ public class FeatureRenderer {
private void addLinearFeature(FeatureCollector.Feature feature, Geometry input) {
long id = idGen.incrementAndGet();
// TODO move to feature?
double minSizeAtMaxZoom = 1d / 4096;
double normalTolerance = 0.1 / 256;
double toleranceAtMaxZoom = 1d / 4096;
boolean area = input instanceof Polygonal;
double worldLength = (area || input.getNumGeometries() > 1) ? 0 : input.getLength();
for (int z = feature.getMaxZoom(); z >= feature.getMinZoom(); z--) {
boolean isMaxZoom = feature.getMaxZoom() == 14;
double scale = 1 << z;
double tolerance = isMaxZoom ? toleranceAtMaxZoom : normalTolerance;
double minSize = isMaxZoom ? minSizeAtMaxZoom : (feature.getMinPixelSize(z) / 256);
double tolerance = feature.getPixelTolerance(z) / 256d;
double minSize = feature.getMinPixelSize(z) / 256d;
if (area) {
minSize *= minSize;
} else if (worldLength > 0 && worldLength * scale < minSize) {

Wyświetl plik

@ -4,6 +4,7 @@ import static com.onthegomap.flatmap.TestUtils.assertSubmap;
import static com.onthegomap.flatmap.TestUtils.newLineString;
import static com.onthegomap.flatmap.TestUtils.newPoint;
import static com.onthegomap.flatmap.TestUtils.newPolygon;
import static com.onthegomap.flatmap.TestUtils.rectangle;
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.onthegomap.flatmap.read.ReaderFeature;
@ -103,7 +104,7 @@ public class FeatureCollectorTest {
.setAttr("attr1", 2)
.setMinPixelSize(1)
.setMinPixelSizeBelowZoom(12, 10);
assertFeatures(14, List.of(
assertFeatures(13, List.of(
Map.of(
"_layer", "layername",
"_minzoom", 12,
@ -134,7 +135,7 @@ public class FeatureCollectorTest {
.inheritFromSource("key")
.setMinPixelSize(1)
.setMinPixelSizeBelowZoom(12, 10);
assertFeatures(14, List.of(
assertFeatures(13, List.of(
Map.of(
"_layer", "layername",
"_minzoom", 12,
@ -152,5 +153,99 @@ public class FeatureCollectorTest {
), collector);
}
@Test
public void testMinSizeAtMaxZoomDefaultsToTileResolution() {
var collector = factory.get(new ReaderFeature(rectangle(10, 20), Map.of()));
var poly = collector.polygon("layername")
.setMinPixelSize(1)
.setMinPixelSizeBelowZoom(12, 10);
assertEquals(10, poly.getMinPixelSize(12));
assertEquals(1, poly.getMinPixelSize(13));
assertEquals(256d / 4096, poly.getMinPixelSize(14));
}
@Test
public void testSetMinSizeAtMaxZoom() {
var collector = factory.get(new ReaderFeature(rectangle(10, 20), Map.of()));
var poly = collector.polygon("layername")
.setMinPixelSize(1)
.setMinPixelSizeAtMaxZoom(0.5)
.setMinPixelSizeBelowZoom(12, 10);
assertEquals(10, poly.getMinPixelSize(12));
assertEquals(1, poly.getMinPixelSize(13));
assertEquals(0.5, poly.getMinPixelSize(14));
}
@Test
public void testSetMinSizeAtAllZooms() {
var collector = factory.get(new ReaderFeature(rectangle(10, 20), Map.of()));
var poly = collector.polygon("layername")
.setMinPixelSizeAtAllZooms(2)
.setMinPixelSizeBelowZoom(12, 10);
assertEquals(10, poly.getMinPixelSize(12));
assertEquals(2, poly.getMinPixelSize(13));
assertEquals(2, poly.getMinPixelSize(14));
}
@Test
public void testDefaultMinPixelSize() {
var collector = factory.get(new ReaderFeature(rectangle(10, 20), Map.of()));
var poly = collector.polygon("layername");
assertEquals(1, poly.getMinPixelSize(12));
assertEquals(1, poly.getMinPixelSize(13));
assertEquals(256d / 4096, poly.getMinPixelSize(14));
}
@Test
public void testToleranceDefault() {
var collector = factory.get(new ReaderFeature(rectangle(10, 20), Map.of()));
var poly = collector.polygon("layername");
assertEquals(0.1, poly.getPixelTolerance(12));
assertEquals(0.1, poly.getPixelTolerance(13));
assertEquals(256d / 4096, poly.getPixelTolerance(14));
}
@Test
public void testSetTolerance() {
var collector = factory.get(new ReaderFeature(rectangle(10, 20), Map.of()));
var poly = collector.polygon("layername")
.setPixelTolerance(1);
assertEquals(1d, poly.getPixelTolerance(12));
assertEquals(1d, poly.getPixelTolerance(13));
assertEquals(256d / 4096, poly.getPixelTolerance(14));
}
@Test
public void testSetToleranceAtAllZooms() {
var collector = factory.get(new ReaderFeature(rectangle(10, 20), Map.of()));
var poly = collector.polygon("layername")
.setPixelToleranceAtAllZooms(1);
assertEquals(1d, poly.getPixelTolerance(12));
assertEquals(1d, poly.getPixelTolerance(13));
assertEquals(1d, poly.getPixelTolerance(14));
}
@Test
public void testSetMaxZoom() {
var collector = factory.get(new ReaderFeature(rectangle(10, 20), Map.of()));
var poly = collector.polygon("layername")
.setPixelToleranceAtMaxZoom(2);
assertEquals(0.1d, poly.getPixelTolerance(12));
assertEquals(0.1d, poly.getPixelTolerance(13));
assertEquals(2d, poly.getPixelTolerance(14));
}
@Test
public void testSetAllZoomMethods() {
var collector = factory.get(new ReaderFeature(rectangle(10, 20), Map.of()));
var poly = collector.polygon("layername")
.setPixelTolerance(1)
.setPixelToleranceAtMaxZoom(2)
.setPixelToleranceBelowZoom(12, 3);
assertEquals(3d, poly.getPixelTolerance(12));
assertEquals(1d, poly.getPixelTolerance(13));
assertEquals(2d, poly.getPixelTolerance(14));
}
// TODO test shape coercion
}

Wyświetl plik

@ -433,6 +433,29 @@ public class FeatureRendererTest {
), renderGeometry(feature));
}
@Test
public void testDuplicatePointsRemovedAfterRounding() {
var eps = Z14_WIDTH / 4096;
var pixel = Z14_WIDTH / 256;
var feature = lineFeature(newLineString(
0.5 + pixel * 10, 0.5 + pixel * 10,
0.5 + pixel * 20, 0.5 + pixel * 10,
0.5 + pixel * 20, 0.5 + pixel * 10 + eps / 3
))
.setMinPixelSize(1)
.setZoomRange(14, 14)
.setBufferPixels(0)
.setPixelToleranceAtAllZooms(0);
assertExactSameFeatures(Map.of(
TileCoord.ofXYZ(Z14_TILES / 2, Z14_TILES / 2, 14), List.of(
newLineString(
10, 10,
20, 10
)
)
), renderGeometry(feature));
}
/*
* POLYGON TESTS
*/