Skip to content

Commit

Permalink
Fix indexing of degenerated rectangles (#67702)
Browse files Browse the repository at this point in the history
This change makes sure we compare encoded values when checking for degenerated rectangles.
  • Loading branch information
iverase authored Jan 20, 2021
1 parent b3dcaa9 commit 2ecc7e2
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
package org.elasticsearch.index.mapper;

import org.apache.lucene.document.LatLonShape;
import org.apache.lucene.geo.GeoEncodingUtils;
import org.apache.lucene.index.IndexableField;
import org.elasticsearch.common.geo.GeoLineDecomposer;
import org.elasticsearch.common.geo.GeoPolygonDecomposer;
Expand Down Expand Up @@ -262,30 +263,47 @@ public Void visit(Polygon polygon) {

@Override
public Void visit(Rectangle r) {
if (r.getMinLon() > r.getMaxLon()) {
if (r.getMinLon() == GeoUtils.MAX_LON) {
Line line = new Line(new double[] {GeoUtils.MAX_LON, GeoUtils.MAX_LON}, new double[] {r.getMaxLat(), r.getMinLat()});
// use encoded values to check equality
final int minLat = GeoEncodingUtils.encodeLatitude(r.getMinLat());
final int maxLat = GeoEncodingUtils.encodeLatitude(r.getMaxLat());
final int minLon = GeoEncodingUtils.encodeLongitude(r.getMinLon());
final int maxLon = GeoEncodingUtils.encodeLongitude(r.getMaxLon());
// check crossing dateline on original values
if (r.getMinLon() > r.getMaxLon()) {
if (minLon == Integer.MAX_VALUE) {
Line line = new Line(new double[]{GeoUtils.MAX_LON, GeoUtils.MAX_LON}, new double[]{r.getMaxLat(), r.getMinLat()});
visit(line);
} else {
Rectangle left = new Rectangle(r.getMinLon(), GeoUtils.MAX_LON, r.getMaxLat(), r.getMinLat());
visit(left);
}
if (r.getMaxLon() == GeoUtils.MIN_LON) {
Line line = new Line(new double[] {GeoUtils.MIN_LON, GeoUtils.MIN_LON}, new double[] {r.getMaxLat(), r.getMinLat()});
if (maxLon == Integer.MIN_VALUE) {
Line line = new Line(new double[]{GeoUtils.MIN_LON, GeoUtils.MIN_LON}, new double[]{r.getMaxLat(), r.getMinLat()});
visit(line);
} else {
Rectangle right = new Rectangle(GeoUtils.MIN_LON, r.getMaxLon(), r.getMaxLat(), r.getMinLat());
visit(right);
}
} else if (r.getMinLon() == r.getMaxLon() || r.getMinLat() == r.getMaxLat()) {
if (r.getMinLat() == r.getMaxLat()) {
addFields(LatLonShape.createIndexableFields(name, r.getMinLat(), r.getMinLon()));
} else {
Line line = new Line(new double[]{r.getMinLon(), r.getMaxLon()}, new double[]{r.getMaxLat(), r.getMinLat()});
visit(line);
}
} else {
addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(r)));
} else if (minLon == maxLon) {
if (minLat == maxLat) {
// rectangle is a point
addFields(LatLonShape.createIndexableFields(name, r.getMinLat(), r.getMinLon()));
} else {
// rectangle is a line
Line line = new Line(new double[]{r.getMinLon(), r.getMaxLon()}, new double[]{r.getMaxLat(), r.getMinLat()});
visit(line);
}
} else if (minLat == maxLat) {
// rectangle is a line
Line line = new Line(new double[]{r.getMinLon(), r.getMaxLon()}, new double[]{r.getMaxLat(), r.getMinLat()});
visit(line);
} else {
// we need to process the quantize rectangle to avoid errors for degenerated boxes
Rectangle qRectangle = new Rectangle(GeoEncodingUtils.decodeLongitude(minLon),
GeoEncodingUtils.decodeLongitude(maxLon),
GeoEncodingUtils.decodeLatitude(maxLat),
GeoEncodingUtils.decodeLatitude(minLat));
addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(qRectangle)));
}
return null;
}
Expand All @@ -294,5 +312,4 @@ private void addFields(IndexableField[] fields) {
this.fields.addAll(Arrays.asList(fields));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,22 @@ public void testDegeneratedRectangles() {
// other side a line
fields = indexer.indexShape(null, indexed);
assertEquals(fields.size(), 2);

indexed = new Rectangle(0.0, 1.0819389717881644E-299, 1.401298464324817E-45, 0.0);
processed = indexer.prepareForIndexing(indexed);
assertEquals(indexed, processed);

// Rectangle is a point
fields = indexer.indexShape(null, processed);
assertEquals(fields.size(), 1);

indexed = new Rectangle(-1.4017117476654298E-170, 0.0, 0.0, -2.415012082648633E-174);
processed = indexer.prepareForIndexing(indexed);
assertEquals(indexed, processed);

// Rectangle is a triangle but needs to be computed quantize
fields = indexer.indexShape(null, processed);
assertEquals(fields.size(), 2);
}

public void testPolygon() {
Expand Down

0 comments on commit 2ecc7e2

Please sign in to comment.