2021-12-23 10:42:24 +00:00
|
|
|
package com.onthegomap.planetiler.geo;
|
2021-04-25 20:29:47 +00:00
|
|
|
|
2021-12-23 10:42:24 +00:00
|
|
|
import static com.onthegomap.planetiler.TestUtils.*;
|
|
|
|
import static com.onthegomap.planetiler.geo.GeoUtils.*;
|
2021-04-25 20:29:47 +00:00
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
|
|
2021-05-25 10:05:41 +00:00
|
|
|
import java.util.List;
|
|
|
|
import org.junit.jupiter.api.Test;
|
2021-04-25 20:29:47 +00:00
|
|
|
import org.junit.jupiter.params.ParameterizedTest;
|
|
|
|
import org.junit.jupiter.params.provider.CsvSource;
|
|
|
|
import org.locationtech.jts.geom.Geometry;
|
2021-07-17 00:48:02 +00:00
|
|
|
import org.locationtech.jts.geom.LinearRing;
|
2021-04-25 20:29:47 +00:00
|
|
|
import org.locationtech.jts.geom.Point;
|
2021-07-17 00:48:02 +00:00
|
|
|
import org.locationtech.jts.geom.util.AffineTransformation;
|
2021-04-25 20:29:47 +00:00
|
|
|
|
2022-04-23 10:36:24 +00:00
|
|
|
class GeoUtilsTest {
|
2021-04-25 20:29:47 +00:00
|
|
|
|
|
|
|
@ParameterizedTest
|
|
|
|
@CsvSource({
|
|
|
|
"0,0, 0.5,0.5",
|
|
|
|
"0, -180, 0, 0.5",
|
2021-06-23 01:46:42 +00:00
|
|
|
"0, 180, 1, 0.5",
|
2021-04-25 20:29:47 +00:00
|
|
|
"0, " + (180 - 1e-7) + ", 1, 0.5",
|
|
|
|
"45, 0, 0.5, 0.359725",
|
2021-06-24 09:26:08 +00:00
|
|
|
"-45, 0, 0.5, " + (1 - 0.359725),
|
|
|
|
"86, -198, -0.05, -0.03391287",
|
|
|
|
"-86, 198, 1.05, 1.03391287",
|
2021-04-25 20:29:47 +00:00
|
|
|
})
|
2022-04-23 10:36:24 +00:00
|
|
|
void testWorldCoords(double lat, double lon, double worldX, double worldY) {
|
2021-04-25 20:29:47 +00:00
|
|
|
assertEquals(worldY, getWorldY(lat), 1e-5);
|
|
|
|
assertEquals(worldX, getWorldX(lon), 1e-5);
|
|
|
|
long encoded = encodeFlatLocation(lon, lat);
|
|
|
|
assertEquals(worldY, decodeWorldY(encoded), 1e-5);
|
|
|
|
assertEquals(worldX, decodeWorldX(encoded), 1e-5);
|
|
|
|
|
|
|
|
Point input = newPoint(lon, lat);
|
|
|
|
Point expected = newPoint(worldX, worldY);
|
2021-05-26 00:53:04 +00:00
|
|
|
Geometry actual = latLonToWorldCoords(input);
|
2021-04-25 20:29:47 +00:00
|
|
|
assertEquals(round(expected), round(actual));
|
2021-05-26 00:53:04 +00:00
|
|
|
|
|
|
|
Geometry roundTripped = worldToLatLonCoords(actual);
|
|
|
|
assertEquals(round(input), round(roundTripped));
|
2021-04-25 20:29:47 +00:00
|
|
|
}
|
2021-05-25 10:05:41 +00:00
|
|
|
|
|
|
|
@Test
|
2022-04-23 10:36:24 +00:00
|
|
|
void testPolygonToLineString() throws GeometryException {
|
2021-05-25 10:05:41 +00:00
|
|
|
assertEquals(newLineString(
|
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
), GeoUtils.polygonToLineString(rectangle(
|
|
|
|
0, 1
|
|
|
|
)));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-04-23 10:36:24 +00:00
|
|
|
void testMultiPolygonToLineString() throws GeometryException {
|
2021-05-25 10:05:41 +00:00
|
|
|
assertEquals(newLineString(
|
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
), GeoUtils.polygonToLineString(newMultiPolygon(rectangle(
|
|
|
|
0, 1
|
|
|
|
))));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-04-23 10:36:24 +00:00
|
|
|
void testLineRingToLineString() throws GeometryException {
|
2021-05-25 10:05:41 +00:00
|
|
|
assertEquals(newLineString(
|
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
), GeoUtils.polygonToLineString(rectangle(
|
|
|
|
0, 1
|
|
|
|
).getExteriorRing()));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-04-23 10:36:24 +00:00
|
|
|
void testComplexPolygonToLineString() throws GeometryException {
|
2021-05-25 10:05:41 +00:00
|
|
|
assertEquals(newMultiLineString(
|
|
|
|
newLineString(
|
|
|
|
0, 0,
|
|
|
|
3, 0,
|
|
|
|
3, 3,
|
|
|
|
0, 3,
|
|
|
|
0, 0
|
|
|
|
), newLineString(
|
|
|
|
1, 1,
|
|
|
|
2, 1,
|
|
|
|
2, 2,
|
|
|
|
1, 2,
|
|
|
|
1, 1
|
|
|
|
)
|
|
|
|
), GeoUtils.polygonToLineString(newPolygon(
|
|
|
|
rectangleCoordList(
|
|
|
|
0, 3
|
|
|
|
), List.of(rectangleCoordList(
|
|
|
|
1, 2
|
|
|
|
)))));
|
|
|
|
}
|
2021-05-26 00:53:04 +00:00
|
|
|
|
|
|
|
@ParameterizedTest
|
|
|
|
@CsvSource({
|
|
|
|
"0, 156543",
|
|
|
|
"8, 611",
|
|
|
|
"14, 9",
|
|
|
|
})
|
2022-04-23 10:36:24 +00:00
|
|
|
void testMetersPerPixel(int zoom, double meters) {
|
2021-05-26 00:53:04 +00:00
|
|
|
assertEquals(meters, metersPerPixelAtEquator(zoom), 1);
|
|
|
|
}
|
2021-07-17 00:48:02 +00:00
|
|
|
|
|
|
|
@Test
|
2022-04-23 10:36:24 +00:00
|
|
|
void testIsConvexTriangle() {
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(true, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-04-23 10:36:24 +00:00
|
|
|
void testIsConvexRectangle() {
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(true, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-04-23 10:36:24 +00:00
|
|
|
void testBarelyConvexRectangle() {
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(true, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0.5, 0.5,
|
|
|
|
0, 0
|
|
|
|
));
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(true, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0.4, 0.4,
|
|
|
|
0, 0
|
|
|
|
));
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(true, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0.7, 0.7,
|
|
|
|
0, 0
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-04-23 10:36:24 +00:00
|
|
|
void testConcaveRectangleDoublePoints() {
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(true, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
));
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(true, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
));
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(true, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
));
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(true, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
));
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(true, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0,
|
|
|
|
0, 0
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-04-23 10:36:24 +00:00
|
|
|
void testBarelyConcaveRectangle() {
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(false, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0.51, 0.5,
|
|
|
|
0, 0
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-04-23 10:36:24 +00:00
|
|
|
void test5PointsConcave() {
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(false, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
0.5, 0.1,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
));
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(false, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
0.9, 0.5,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
));
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(false, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0.5, 0.9,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
));
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(false, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0.1, 0.5,
|
|
|
|
0, 0
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-04-23 10:36:24 +00:00
|
|
|
void test5PointsColinear() {
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(true, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
0.5, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
));
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(true, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 0.5,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
));
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(true, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0.5, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0
|
|
|
|
));
|
2023-01-26 09:59:37 +00:00
|
|
|
assertConvex(true, newLinearRing(
|
2021-07-17 00:48:02 +00:00
|
|
|
0, 0,
|
|
|
|
1, 0,
|
|
|
|
1, 1,
|
|
|
|
0, 1,
|
|
|
|
0, 0.5,
|
|
|
|
0, 0
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2023-01-26 09:59:37 +00:00
|
|
|
private static void assertConvex(boolean isConvex, LinearRing ring) {
|
2021-07-17 00:48:02 +00:00
|
|
|
for (double rotation : new double[]{0, 90, 180, 270}) {
|
|
|
|
LinearRing rotated = (LinearRing) AffineTransformation.rotationInstance(Math.toRadians(rotation)).transform(ring);
|
|
|
|
for (boolean flip : new boolean[]{false, true}) {
|
|
|
|
LinearRing flipped = flip ? (LinearRing) AffineTransformation.scaleInstance(-1, 1).transform(rotated) : rotated;
|
|
|
|
for (boolean reverse : new boolean[]{false, true}) {
|
|
|
|
LinearRing reversed = reverse ? flipped.reverse() : flipped;
|
2023-01-26 09:59:37 +00:00
|
|
|
assertEquals(isConvex, isConvex(reversed), "rotation=" + rotation + " flip=" + flip + " reverse=" + reverse);
|
2021-07-17 00:48:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-03-19 19:16:11 +00:00
|
|
|
|
|
|
|
@Test
|
2022-04-23 10:36:24 +00:00
|
|
|
void testCombineEmpty() {
|
2022-03-19 19:16:11 +00:00
|
|
|
assertEquals(EMPTY_GEOMETRY, GeoUtils.combine());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-04-23 10:36:24 +00:00
|
|
|
void testCombineOne() {
|
2022-03-19 19:16:11 +00:00
|
|
|
assertEquals(newLineString(0, 0, 1, 1), GeoUtils.combine(newLineString(0, 0, 1, 1)));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-04-23 10:36:24 +00:00
|
|
|
void testCombineTwo() {
|
2022-03-19 19:16:11 +00:00
|
|
|
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
|
2022-04-23 10:36:24 +00:00
|
|
|
void testCombineNested() {
|
2022-03-19 19:16:11 +00:00
|
|
|
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)
|
|
|
|
));
|
|
|
|
}
|
2021-04-25 20:29:47 +00:00
|
|
|
}
|