Handle more than one centerline for a lake (#139)

pull/140/head
Michael Barry 2022-03-19 15:16:11 -04:00 zatwierdzone przez GitHub
rodzic bf081692ce
commit 313a695abb
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
5 zmienionych plików z 113 dodań i 2 usunięć

Wyświetl plik

@ -111,7 +111,13 @@ public class WaterName implements
try {
// multiple threads call this concurrently
synchronized (this) {
lakeCenterlines.put(osmId, feature.worldGeometry());
// if we already have a centerline for this OSM_ID, then merge the existing one with this one
var newGeometry = feature.worldGeometry();
var oldGeometry = lakeCenterlines.get(osmId);
if (oldGeometry != null) {
newGeometry = GeoUtils.combine(oldGeometry, newGeometry);
}
lakeCenterlines.put(osmId, newGeometry);
}
} catch (GeometryException e) {
e.log(stats, "omt_water_name_lakeline", "Bad lake centerline: " + feature);

Wyświetl plik

@ -13,6 +13,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.locationtech.jts.geom.Geometry;
public class WaterNameTest extends AbstractLayerTest {
@ -89,6 +90,56 @@ public class WaterNameTest extends AbstractLayerTest {
)));
}
@Test
public void testWaterNameMultipleLakelines() {
assertFeatures(11, List.of(), process(SimpleFeature.create(
newLineString(0, 0, 1, 1),
new HashMap<>(Map.<String, Object>of(
"OSM_ID", -10
)),
LAKE_CENTERLINE_SOURCE,
null,
0
)));
assertFeatures(11, List.of(), process(SimpleFeature.create(
newLineString(2, 2, 3, 3),
new HashMap<>(Map.<String, Object>of(
"OSM_ID", -10
)),
LAKE_CENTERLINE_SOURCE,
null,
0
)));
assertFeatures(10, List.of(Map.of(
"_layer", "water"
), Map.of(
"name", "waterway",
"name:es", "waterway es",
"_layer", "water_name",
"_geom",
new TestUtils.NormGeometry(
GeoUtils.latLonToWorldCoords(GeoUtils.JTS_FACTORY.createGeometryCollection(new Geometry[]{
newLineString(0, 0, 1, 1),
newLineString(2, 2, 3, 3)
}))),
"_minzoom", 9,
"_maxzoom", 14,
"_minpixelsize", "waterway".length() * 6d
)), process(SimpleFeature.create(
GeoUtils.worldToLatLonCoords(rectangle(0, Math.sqrt(1))),
new HashMap<>(Map.<String, Object>of(
"name", "waterway",
"name:es", "waterway es",
"natural", "water",
"water", "pond"
)),
OSM_SOURCE,
null,
10
)));
}
@Test
public void testMarinePoint() {
assertFeatures(11, List.of(), process(SimpleFeature.create(

Wyświetl plik

@ -480,6 +480,23 @@ public class GeoUtils {
}
}
/** Combines multiple geometries into one {@link GeometryCollection}. */
public static Geometry combine(Geometry... geometries) {
List<Geometry> innerGeometries = new ArrayList<>();
// attempt to flatten out nested geometry collections
for (var geom : geometries) {
if (geom instanceof GeometryCollection collection) {
for (int i = 0; i < collection.getNumGeometries(); i++) {
innerGeometries.add(collection.getGeometryN(i));
}
} else {
innerGeometries.add(geom);
}
}
return innerGeometries.size() == 1 ? innerGeometries.get(0) :
JTS_FACTORY.createGeometryCollection(innerGeometries.toArray(Geometry[]::new));
}
/** Helper class to sort polygons by area of their outer shell. */
private record PolyAndArea(Polygon poly, double area) implements Comparable<PolyAndArea> {

Wyświetl plik

@ -384,7 +384,8 @@ public class TestUtils {
result.put("_labelgrid_limit", feature.getPointLabelGridLimitAtZoom(zoom));
result.put("_labelgrid_size", feature.getPointLabelGridPixelSizeAtZoom(zoom));
result.put("_minpixelsize", feature.getMinPixelSizeAtZoom(zoom));
result.put("_type", geom instanceof Puntal ? "point" : geom instanceof Lineal ? "line" : "polygon");
result.put("_type", geom instanceof Puntal ? "point" : geom instanceof Lineal ? "line" :
geom instanceof Polygonal ? "polygon" : geom.getClass().getSimpleName());
result.put("_numpointsattr", feature.getNumPointsAttr());
return result;
}

Wyświetl plik

@ -300,4 +300,40 @@ public class GeoUtilsTest {
}
}
}
@Test
public void testCombineEmpty() {
assertEquals(EMPTY_GEOMETRY, GeoUtils.combine());
}
@Test
public void testCombineOne() {
assertEquals(newLineString(0, 0, 1, 1), GeoUtils.combine(newLineString(0, 0, 1, 1)));
}
@Test
public void testCombineTwo() {
assertEquals(GeoUtils.JTS_FACTORY.createGeometryCollection(new Geometry[]{
newLineString(0, 0, 1, 1),
newLineString(2, 2, 3, 3)
}), GeoUtils.combine(
newLineString(0, 0, 1, 1),
newLineString(2, 2, 3, 3)
));
}
@Test
public void testCombineNested() {
assertEquals(GeoUtils.JTS_FACTORY.createGeometryCollection(new Geometry[]{
newLineString(0, 0, 1, 1),
newLineString(2, 2, 3, 3),
newLineString(4, 4, 5, 5)
}), GeoUtils.combine(
GeoUtils.combine(
newLineString(0, 0, 1, 1),
newLineString(2, 2, 3, 3)
),
newLineString(4, 4, 5, 5)
));
}
}