LUCENE-8236: Filter duplicated points when creating GeoPath shapes to avoid creation of bogus planes.

This commit is contained in:
Ignacio Vera 2018-04-04 13:33:42 +02:00
parent 7117b68db6
commit cf56890400
3 changed files with 46 additions and 2 deletions

View File

@ -120,6 +120,9 @@ Bug Fixes
* LUCENE-8234: Fixed bug in how spatial relationship is computed for
GeoStandardCircle when it covers the whole world. (Ignacio Vera)
* LUCENE-8236: Filter duplicated points when creating GeoPath shapes to
avoid creation of bogus planes. (Ignacio Vera)
Other
* LUCENE-8228: removed obsolete IndexDeletionPolicy clone() requirements from

View File

@ -16,6 +16,9 @@
*/
package org.apache.lucene.spatial3d.geom;
import java.util.ArrayList;
import java.util.List;
/**
* Class which constructs a GeoPath representing an arbitrary path.
*
@ -34,9 +37,24 @@ public class GeoPathFactory {
*/
public static GeoPath makeGeoPath(final PlanetModel planetModel, final double maxCutoffAngle, final GeoPoint[] pathPoints) {
if (maxCutoffAngle < Vector.MINIMUM_ANGULAR_RESOLUTION) {
return new GeoDegeneratePath(planetModel, pathPoints);
return new GeoDegeneratePath(planetModel, filterPoints(pathPoints));
}
return new GeoStandardPath(planetModel, maxCutoffAngle, pathPoints);
return new GeoStandardPath(planetModel, maxCutoffAngle, filterPoints(pathPoints));
}
/** Filter duplicate points.
* @param pathPoints with the arras of points.
* @return the filtered array.
*/
private static GeoPoint[] filterPoints(final GeoPoint[] pathPoints) {
final List<GeoPoint> noIdenticalPoints = new ArrayList<>(pathPoints.length);
for (int i = 0; i < pathPoints.length - 1; i++) {
if (!pathPoints[i].isNumericallyIdentical(pathPoints[i + 1])) {
noIdenticalPoints.add(pathPoints[i]);
}
}
noIdenticalPoints.add(pathPoints[pathPoints.length - 1]);
return noIdenticalPoints.toArray(new GeoPoint[noIdenticalPoints.size()]);
}
}

View File

@ -379,4 +379,27 @@ public class GeoPathTest {
}
@Test
public void testIdenticalPoints() {
PlanetModel planetModel = PlanetModel.WGS84;
GeoPoint point1 = new GeoPoint(planetModel, 1.5707963267948963, -2.4818290647609542E-148);
GeoPoint point2 = new GeoPoint(planetModel, 1.570796326794895, -3.5E-323);
GeoPoint point3 = new GeoPoint(planetModel,4.4E-323, -3.1415926535897896);
GeoPath path = GeoPathFactory.makeGeoPath(planetModel, 0, new GeoPoint[] {point1, point2, point3});
GeoPoint point = new GeoPoint(planetModel, -1.5707963267948952,2.369064805649877E-284);
//If not filtered the point is wrongly in set
assertFalse(path.isWithin(point));
//If not filtered it throws error
path = GeoPathFactory.makeGeoPath(planetModel, 1e-6, new GeoPoint[] {point1, point2, point3});
assertFalse(path.isWithin(point));
GeoPoint point4 = new GeoPoint(planetModel, 1.5, 0);
GeoPoint point5 = new GeoPoint(planetModel, 1.5, 0);
GeoPoint point6 = new GeoPoint(planetModel,4.4E-323, -3.1415926535897896);
//If not filtered creates a degenerated Vector
path = GeoPathFactory.makeGeoPath(planetModel, 0, new GeoPoint[] {point4, point5, point6});
path = GeoPathFactory.makeGeoPath(planetModel, 0.5, new GeoPoint[] {point4, point5, point6});
}
}