|
@@ -38,8 +38,10 @@ import org.elasticsearch.test.ESTestCase;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
import java.text.ParseException;
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
|
|
|
import static org.hamcrest.Matchers.instanceOf;
|
|
|
|
|
@@ -155,16 +157,40 @@ public class GeometryIndexerTests extends ESTestCase {
|
|
|
*/
|
|
|
public double length(Line line) {
|
|
|
double distance = 0;
|
|
|
+ double[] prev = new double[]{line.getLon(0), line.getLat(0)};
|
|
|
+ GeoUtils.normalizePoint(prev, false, true);
|
|
|
for (int i = 1; i < line.length(); i++) {
|
|
|
- distance += Math.sqrt((line.getLat(i) - line.getLat(i - 1)) * (line.getLat(i) - line.getLat(i - 1)) +
|
|
|
- (line.getLon(i) - line.getLon(i - 1)) * (line.getLon(i) - line.getLon(i - 1)));
|
|
|
+ double[] cur = new double[]{line.getLon(i), line.getLat(i)};
|
|
|
+ GeoUtils.normalizePoint(cur, false, true);
|
|
|
+ distance += Math.sqrt((cur[0] - prev[0]) * (cur[0] - prev[0]) + (cur[1] - prev[1]) * (cur[1] - prev[1]));
|
|
|
+ prev = cur;
|
|
|
}
|
|
|
return distance;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * A simple tests that generates a random lines crossing anti-merdian and checks that the decomposed segments of this line
|
|
|
+ * Removes the points on the antimeridian that are introduced during linestring decomposition
|
|
|
+ */
|
|
|
+ public static MultiPoint remove180s(MultiPoint points) {
|
|
|
+ List<Point> list = new ArrayList<>();
|
|
|
+ points.forEach(point -> {
|
|
|
+ if (Math.abs(point.getLon()) - 180.0 > 0.000001) {
|
|
|
+ list.add(point);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (list.isEmpty()) {
|
|
|
+ return MultiPoint.EMPTY;
|
|
|
+ }
|
|
|
+ return new MultiPoint(list);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * A randomized test that generates a random lines crossing anti-merdian and checks that the decomposed segments of this line
|
|
|
* have the same total length (measured using Euclidean distances between neighboring points) as the original line.
|
|
|
+ *
|
|
|
+ * It also extracts all points from these lines, performs normalization of these points and then compares that the resulting
|
|
|
+ * points of line normalization match the points of points normalization with the exception of points that were created on the
|
|
|
+ * antimeridian as the result of line decomposition.
|
|
|
*/
|
|
|
public void testRandomLine() {
|
|
|
int size = randomIntBetween(2, 20);
|
|
@@ -172,8 +198,10 @@ public class GeometryIndexerTests extends ESTestCase {
|
|
|
double[] originalLats = new double[size];
|
|
|
double[] originalLons = new double[size];
|
|
|
|
|
|
+ // Generate a random line that goes over poles and stretches beyond -180 and +180
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
- originalLats[i] = GeometryTestUtils.randomLat();
|
|
|
+ // from time to time go over poles
|
|
|
+ originalLats[i] = randomInt(4) == 0 ? GeometryTestUtils.randomLat() : GeometryTestUtils.randomLon();
|
|
|
originalLons[i] = GeometryTestUtils.randomLon() + shift * 360;
|
|
|
if (randomInt(3) == 0) {
|
|
|
shift += randomFrom(-2, -1, 1, 2);
|
|
@@ -181,6 +209,7 @@ public class GeometryIndexerTests extends ESTestCase {
|
|
|
}
|
|
|
Line original = new Line(originalLons, originalLats);
|
|
|
|
|
|
+ // Check that the length of original and decomposed lines is the same
|
|
|
Geometry decomposed = indexer.prepareForIndexing(original);
|
|
|
double decomposedLength = 0;
|
|
|
if (decomposed instanceof Line) {
|
|
@@ -192,8 +221,19 @@ public class GeometryIndexerTests extends ESTestCase {
|
|
|
decomposedLength += length(lines.get(i));
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
assertEquals("Different Lengths between " + original + " and " + decomposed, length(original), decomposedLength, 0.001);
|
|
|
+
|
|
|
+ // Check that normalized linestring generates the same points as the normalized multipoint based on the same set of points
|
|
|
+ MultiPoint decomposedViaLines = remove180s(GeometryTestUtils.toMultiPoint(decomposed));
|
|
|
+ MultiPoint originalPoints = GeometryTestUtils.toMultiPoint(original);
|
|
|
+ MultiPoint decomposedViaPoint = remove180s(GeometryTestUtils.toMultiPoint(indexer.prepareForIndexing(originalPoints)));
|
|
|
+ assertEquals(decomposedViaPoint.size(), decomposedViaLines.size());
|
|
|
+ for (int i=0; i<decomposedViaPoint.size(); i++) {
|
|
|
+ assertEquals("Difference between decomposing lines " + decomposedViaLines + " and points " + decomposedViaPoint +
|
|
|
+ " at the position " + i, decomposedViaPoint.get(i).getLat(), decomposedViaLines.get(i).getLat(), 0.0001);
|
|
|
+ assertEquals("Difference between decomposing lines " + decomposedViaLines + " and points " + decomposedViaPoint +
|
|
|
+ " at the position " + i, decomposedViaPoint.get(i).getLon(), decomposedViaLines.get(i).getLon(), 0.0001);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public void testMultiLine() {
|
|
@@ -231,6 +271,9 @@ public class GeometryIndexerTests extends ESTestCase {
|
|
|
|
|
|
point = new Point(180, 180);
|
|
|
assertEquals(new Point(0, 0), indexer.prepareForIndexing(point));
|
|
|
+
|
|
|
+ point = new Point(-180, -180);
|
|
|
+ assertEquals(new Point(0, 0), indexer.prepareForIndexing(point));
|
|
|
}
|
|
|
|
|
|
public void testMultiPoint() {
|