Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Min polygon area centroid #720

Merged
merged 3 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ private Feature(String layer, Geometry geom, long id) {
this.geom = geom;
this.geometryType = GeometryType.typeOf(geom);
this.id = id;
if (geometryType == GeometryType.POINT) {
minPixelSizeAtMaxZoom = 0;
defaultMinPixelSize = 0;
}
}

/** Returns the original ID of the source feature that this feature came from (i.e. OSM node/way ID). */
Expand Down Expand Up @@ -728,5 +732,15 @@ public String toString() {
", attrs=" + attrs +
'}';
}

/** Returns the actual pixel size of the source feature at {@code zoom} (length if line, sqrt(area) if polygon). */
public double getSourceFeaturePixelSizeAtZoom(int zoom) {
try {
return source.size() * (256 << zoom);
} catch (GeometryException e) {
e.log(stats, "point_get_size_failure", "Error getting min size for point from geometry " + source.id());
return 0;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public abstract class SourceFeature implements WithTags, WithGeometryType {
private Geometry validPolygon = null;
private double area = Double.NaN;
private double length = Double.NaN;
private double size = Double.NaN;

/**
* Constructs a new input feature.
Expand Down Expand Up @@ -245,6 +246,14 @@ public double length() throws GeometryException {
(isPoint() || canBePolygon() || canBeLine()) ? worldGeometry().getLength() : 0) : length;
}

/**
* Returns and caches sqrt of {@link #area()} if polygon or {@link #length()} if a line string.
*/
public double size() throws GeometryException {
return Double.isNaN(size) ? (size = canBePolygon() ? Math.sqrt(Math.abs(area())) : canBeLine() ? length() : 0) :
size;
}

/** Returns the ID of the source that this feature came from. */
public String getSource() {
return source;
Expand Down Expand Up @@ -292,4 +301,5 @@ public final long id() {
public boolean hasRelationInfo() {
return relationInfos != null && !relationInfos.isEmpty();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ private void renderPoint(FeatureCollector.Feature feature, Coordinate... origCoo
coords[i] = origCoords[i].copy();
}
for (int zoom = feature.getMaxZoom(); zoom >= feature.getMinZoom(); zoom--) {
double minSize = feature.getMinPixelSizeAtZoom(zoom);
if (minSize > 0 && feature.getSourceFeaturePixelSizeAtZoom(zoom) < minSize) {
continue;
}
Map<String, Object> attrs = feature.getAttrsAtZoom(zoom);
double buffer = feature.getBufferPixelsAtZoom(zoom) / 256;
int tilesAtZoom = 1 << zoom;
Expand Down Expand Up @@ -207,7 +211,7 @@ private void renderLineOrPolygon(FeatureCollector.Feature feature, Geometry inpu
}
Map<String, Object> attrs = feature.getAttrsAtZoom(sliced.zoomLevel());
if (numPointsAttr != null) {
// if profile wants the original number of points that the simplified but untiled geometry started with
// if profile wants the original number off points that the simplified but untiled geometry started with
attrs = new HashMap<>(attrs);
attrs.put(numPointsAttr, geom.getNumPoints());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -614,5 +614,4 @@ void testManyAttr() {
)
), collector);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,15 @@ public List<Coordinate> z14CoordinateList(double... coords) {
return points;
}

public List<Coordinate> z14PixelRectangle(double min, double max) {
List<Coordinate> points = rectangleCoordList(min / 256d, max / 256d);
points.forEach(c -> {
c.x = GeoUtils.getWorldLon(0.5 + c.x * Z14_WIDTH);
c.y = GeoUtils.getWorldLat(0.5 + c.y * Z14_WIDTH);
});
return points;
}

public List<Coordinate> z14CoordinatePixelList(double... coords) {
return z14CoordinateList(DoubleStream.of(coords).map(c -> c / 256d).toArray());
}
Expand Down Expand Up @@ -2341,6 +2350,90 @@ void testBoundFilters() throws Exception {
assertEquals(bboxResult.tiles, polyResult.tiles);
}

@Test
void testSimplePolygon() throws Exception {
List<Coordinate> points = z14PixelRectangle(0, 40);

var results = runWithReaderFeatures(
Map.of("threads", "1"),
List.of(
newReaderFeature(newPolygon(points), Map.of())
),
(in, features) -> features.polygon("layer")
.setZoomRange(0, 14)
.setBufferPixels(0)
.setMinPixelSize(10) // should only show up z14 (40) z13 (20) and z12 (10)
);

assertEquals(Map.ofEntries(
newTileEntry(Z12_TILES / 2, Z12_TILES / 2, 12, List.of(
feature(newPolygon(rectangleCoordList(0, 10)), Map.of())
)),
newTileEntry(Z13_TILES / 2, Z13_TILES / 2, 13, List.of(
feature(newPolygon(rectangleCoordList(0, 20)), Map.of())
)),
newTileEntry(Z14_TILES / 2, Z14_TILES / 2, 14, List.of(
feature(newPolygon(rectangleCoordList(0, 40)), Map.of())
))
), results.tiles);
}

@Test
void testCentroidWithPolygonMinSize() throws Exception {
List<Coordinate> points = z14PixelRectangle(0, 40);

var results = runWithReaderFeatures(
Map.of("threads", "1"),
List.of(
newReaderFeature(newPolygon(points), Map.of())
),
(in, features) -> features.centroid("layer")
.setZoomRange(0, 14)
.setBufferPixels(0)
.setMinPixelSize(10) // should only show up z14 (40) z13 (20) and z12 (10)
);

assertEquals(Map.ofEntries(
newTileEntry(Z12_TILES / 2, Z12_TILES / 2, 12, List.of(
feature(newPoint(5, 5), Map.of())
)),
newTileEntry(Z13_TILES / 2, Z13_TILES / 2, 13, List.of(
feature(newPoint(10, 10), Map.of())
)),
newTileEntry(Z14_TILES / 2, Z14_TILES / 2, 14, List.of(
feature(newPoint(20, 20), Map.of())
))
), results.tiles);
}

@Test
void testCentroidWithLineMinSize() throws Exception {
List<Coordinate> points = z14CoordinatePixelList(0, 4, 40, 4);

var results = runWithReaderFeatures(
Map.of("threads", "1"),
List.of(
newReaderFeature(newLineString(points), Map.of())
),
(in, features) -> features.centroid("layer")
.setZoomRange(0, 14)
.setBufferPixels(0)
.setMinPixelSize(10) // should only show up z14 (40) z13 (20) and z12 (10)
);

assertEquals(Map.ofEntries(
newTileEntry(Z12_TILES / 2, Z12_TILES / 2, 12, List.of(
feature(newPoint(5, 1), Map.of())
)),
newTileEntry(Z13_TILES / 2, Z13_TILES / 2, 13, List.of(
feature(newPoint(10, 2), Map.of())
)),
newTileEntry(Z14_TILES / 2, Z14_TILES / 2, 14, List.of(
feature(newPoint(20, 4), Map.of())
))
), results.tiles);
}

@Test
void testBoundFiltersFill() throws Exception {
var polyResultz8 = runForBoundsTest(8, 8, "polygon", TestUtils.pathToResource("bottomrightearth.poly").toString());
Expand Down
Loading