mirror of https://github.com/apache/lucene.git
LUCENE-9218: XYGeometries should expose values as floats (#1252)
This commit is contained in:
parent
5cbe58f22c
commit
4a54ffb553
|
@ -108,6 +108,8 @@ API Changes
|
|||
|
||||
* LUCENE-8621: Refactor LatLonShape, XYShape, and all query and utility classes to core. (Nick Knize)
|
||||
|
||||
* LUCENE-9218: XY geometries API works in float space. (Ignacio Vera)
|
||||
|
||||
New Features
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ final class Line2D implements Component2D {
|
|||
this.maxY = line.maxY;
|
||||
this.minX = line.minX;
|
||||
this.maxX = line.maxX;
|
||||
this.tree = EdgeTree.createTree(line.getX(), line.getY());
|
||||
this.tree = EdgeTree.createTree(XYEncodingUtils.floatArrayToDoubleArray(line.getX()), XYEncodingUtils.floatArrayToDoubleArray(line.getY()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -49,10 +49,10 @@ final class Polygon2D implements Component2D {
|
|||
}
|
||||
|
||||
private Polygon2D(XYPolygon polygon, Component2D holes) {
|
||||
this(polygon.minX, polygon.maxX, polygon.minY, polygon.maxY, polygon.getPolyX(), polygon.getPolyY(), holes);
|
||||
this(polygon.minX, polygon.maxX, polygon.minY, polygon.maxY, XYEncodingUtils.floatArrayToDoubleArray(polygon.getPolyX()), XYEncodingUtils.floatArrayToDoubleArray(polygon.getPolyY()), holes);
|
||||
}
|
||||
|
||||
protected Polygon2D(Polygon polygon, Component2D holes) {
|
||||
private Polygon2D(Polygon polygon, Component2D holes) {
|
||||
this(polygon.minLon, polygon.maxLon, polygon.minLat, polygon.maxLat, polygon.getPolyLons(), polygon.getPolyLats(), holes);
|
||||
}
|
||||
|
||||
|
|
|
@ -122,9 +122,9 @@ final public class Tessellator {
|
|||
|
||||
public static final List<Triangle> tessellate(final XYPolygon polygon) {
|
||||
// Attempt to establish a doubly-linked list of the provided shell points (should be CCW, but this will correct);
|
||||
// then filter instances of intersections.
|
||||
Node outerNode = createDoublyLinkedList(polygon.getPolyX(), polygon.getPolyY(), polygon.getWindingOrder(), false,
|
||||
0, WindingOrder.CW);
|
||||
// then filter instances of intersections.0
|
||||
Node outerNode = createDoublyLinkedList(XYEncodingUtils.floatArrayToDoubleArray(polygon.getPolyX()), XYEncodingUtils.floatArrayToDoubleArray(polygon.getPolyY()),
|
||||
polygon.getWindingOrder(), false, 0, WindingOrder.CW);
|
||||
// If an outer node hasn't been detected, the shape is malformed. (must comply with OGC SFA specification)
|
||||
if(outerNode == null) {
|
||||
throw new IllegalArgumentException("Malformed shape detected in Tessellator!");
|
||||
|
@ -193,7 +193,8 @@ final public class Tessellator {
|
|||
int nodeIndex = polygon.numPoints() ;
|
||||
for(int i = 0; i < polygon.numHoles(); ++i) {
|
||||
// create the doubly-linked hole list
|
||||
Node list = createDoublyLinkedList(holes[i].getPolyX(), holes[i].getPolyY(), holes[i].getWindingOrder(), false, nodeIndex, WindingOrder.CCW);
|
||||
Node list = createDoublyLinkedList(XYEncodingUtils.floatArrayToDoubleArray(holes[i].getPolyX()),
|
||||
XYEncodingUtils.floatArrayToDoubleArray(holes[i].getPolyY()), holes[i].getWindingOrder(), false, nodeIndex, WindingOrder.CCW);
|
||||
// Determine if the resulting hole polygon was successful.
|
||||
if(list != null) {
|
||||
// Add the leftmost vertex of the hole.
|
||||
|
@ -1059,8 +1060,9 @@ final public class Tessellator {
|
|||
this.vrtxIdx = vertexIndex;
|
||||
this.polyX = x;
|
||||
this.polyY = y;
|
||||
this.y = isGeo ? encodeLatitude(polyY[vrtxIdx]) : XYEncodingUtils.encode(polyY[vrtxIdx]);
|
||||
this.x = isGeo ? encodeLongitude(polyX[vrtxIdx]) : XYEncodingUtils.encode(polyX[vrtxIdx]);
|
||||
// casting to float is safe as original values for non-geo are represented as floats
|
||||
this.y = isGeo ? encodeLatitude(polyY[vrtxIdx]) : XYEncodingUtils.encode((float) polyY[vrtxIdx]);
|
||||
this.x = isGeo ? encodeLongitude(polyX[vrtxIdx]) : XYEncodingUtils.encode((float) polyX[vrtxIdx]);
|
||||
this.morton = BitUtil.interleave(this.x ^ 0x80000000, this.y ^ 0x80000000);
|
||||
this.previous = null;
|
||||
this.next = null;
|
||||
|
|
|
@ -33,11 +33,12 @@ public final class XYEncodingUtils {
|
|||
private XYEncodingUtils() {
|
||||
}
|
||||
|
||||
/** validates value is within +/-{@link Float#MAX_VALUE} coordinate bounds */
|
||||
public static void checkVal(double x) {
|
||||
if (Double.isNaN(x) || x < MIN_VAL_INCL || x > MAX_VAL_INCL) {
|
||||
/** validates value is a number and finite */
|
||||
static float checkVal(float x) {
|
||||
if (Float.isFinite(x) == false) {
|
||||
throw new IllegalArgumentException("invalid value " + x + "; must be between " + MIN_VAL_INCL + " and " + MAX_VAL_INCL);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,9 +47,8 @@ public final class XYEncodingUtils {
|
|||
* @return encoded value as a 32-bit {@code int}
|
||||
* @throws IllegalArgumentException if value is out of bounds
|
||||
*/
|
||||
public static int encode(double x) {
|
||||
checkVal(x);
|
||||
return NumericUtils.floatToSortableInt((float)x);
|
||||
public static int encode(float x) {
|
||||
return NumericUtils.floatToSortableInt(checkVal(x));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,8 +56,8 @@ public final class XYEncodingUtils {
|
|||
* @param encoded encoded value: 32-bit quantized value.
|
||||
* @return decoded value value.
|
||||
*/
|
||||
public static double decode(int encoded) {
|
||||
double result = NumericUtils.sortableIntToFloat(encoded);
|
||||
public static float decode(int encoded) {
|
||||
float result = NumericUtils.sortableIntToFloat(encoded);
|
||||
assert result >= MIN_VAL_INCL && result <= MAX_VAL_INCL;
|
||||
return result;
|
||||
}
|
||||
|
@ -68,7 +68,15 @@ public final class XYEncodingUtils {
|
|||
* @param offset offset into {@code src} to decode from.
|
||||
* @return decoded value.
|
||||
*/
|
||||
public static double decode(byte[] src, int offset) {
|
||||
public static float decode(byte[] src, int offset) {
|
||||
return decode(NumericUtils.sortableBytesToInt(src, offset));
|
||||
}
|
||||
|
||||
static double[] floatArrayToDoubleArray(float[] f) {
|
||||
double[] d = new double[f.length];
|
||||
for (int i = 0; i < f.length; i++) {
|
||||
d[i] = f[i];
|
||||
}
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,24 +18,26 @@ package org.apache.lucene.geo;
|
|||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.apache.lucene.geo.XYEncodingUtils.checkVal;
|
||||
|
||||
/**
|
||||
* Represents a line in cartesian space. You can construct the Line directly with {@code float[]}, {@code float[]} x, y arrays
|
||||
* coordinates.
|
||||
*/
|
||||
public class XYLine extends XYGeometry {
|
||||
/** array of x coordinates */
|
||||
private final double[] x;
|
||||
private final float[] x;
|
||||
/** array of y coordinates */
|
||||
private final double[] y;
|
||||
private final float[] y;
|
||||
|
||||
/** minimum x of this line's bounding box */
|
||||
public final double minX;
|
||||
public final float minX;
|
||||
/** maximum y of this line's bounding box */
|
||||
public final double maxX;
|
||||
public final float maxX;
|
||||
/** minimum y of this line's bounding box */
|
||||
public final double minY;
|
||||
public final float minY;
|
||||
/** maximum y of this line's bounding box */
|
||||
public final double maxY;
|
||||
public final float maxY;
|
||||
|
||||
/**
|
||||
* Creates a new Line from the supplied X/Y array.
|
||||
|
@ -55,23 +57,19 @@ public class XYLine extends XYGeometry {
|
|||
}
|
||||
|
||||
// compute bounding box
|
||||
double minX = x[0];
|
||||
double minY = y[0];
|
||||
double maxX = x[0];
|
||||
double maxY = y[0];
|
||||
float minX = Float.MAX_VALUE;
|
||||
float minY = Float.MAX_VALUE;
|
||||
float maxX = -Float.MAX_VALUE;
|
||||
float maxY = -Float.MAX_VALUE;
|
||||
for (int i = 0; i < x.length; ++i) {
|
||||
minX = Math.min(x[i], minX);
|
||||
minY = Math.min(y[i], minY);
|
||||
minX = Math.min(checkVal(x[i]), minX);
|
||||
minY = Math.min(checkVal(y[i]), minY);
|
||||
maxX = Math.max(x[i], maxX);
|
||||
maxY = Math.max(y[i], maxY);
|
||||
}
|
||||
this.x = x.clone();
|
||||
this.y = y.clone();
|
||||
|
||||
this.x = new double[x.length];
|
||||
this.y = new double[y.length];
|
||||
for (int i = 0; i < x.length; ++i) {
|
||||
this.x[i] = (double)x[i];
|
||||
this.y[i] = (double)y[i];
|
||||
}
|
||||
this.minX = minX;
|
||||
this.maxX = maxX;
|
||||
this.minY = minY;
|
||||
|
@ -84,22 +82,22 @@ public class XYLine extends XYGeometry {
|
|||
}
|
||||
|
||||
/** Returns x value at given index */
|
||||
public double getX(int vertex) {
|
||||
public float getX(int vertex) {
|
||||
return x[vertex];
|
||||
}
|
||||
|
||||
/** Returns y value at given index */
|
||||
public double getY(int vertex) {
|
||||
public float getY(int vertex) {
|
||||
return y[vertex];
|
||||
}
|
||||
|
||||
/** Returns a copy of the internal x array */
|
||||
public double[] getX() {
|
||||
public float[] getX() {
|
||||
return x.clone();
|
||||
}
|
||||
|
||||
/** Returns a copy of the internal y array */
|
||||
public double[] getY() {
|
||||
public float[] getY() {
|
||||
return y.clone();
|
||||
}
|
||||
|
||||
|
@ -108,14 +106,6 @@ public class XYLine extends XYGeometry {
|
|||
return Line2D.create(this);
|
||||
}
|
||||
|
||||
public String toGeoJSON() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[");
|
||||
sb.append(Polygon.verticesToGeoJSON(x, y));
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
package org.apache.lucene.geo;
|
||||
|
||||
import static org.apache.lucene.geo.XYEncodingUtils.checkVal;
|
||||
|
||||
/**
|
||||
* Represents a point on the earth's surface. You can construct the point directly with {@code double}
|
||||
* coordinates.
|
||||
|
@ -30,25 +32,25 @@ package org.apache.lucene.geo;
|
|||
public final class XYPoint extends XYGeometry {
|
||||
|
||||
/** latitude coordinate */
|
||||
private final double x;
|
||||
private final float x;
|
||||
/** longitude coordinate */
|
||||
private final double y;
|
||||
private final float y;
|
||||
|
||||
/**
|
||||
* Creates a new Point from the supplied latitude/longitude.
|
||||
*/
|
||||
public XYPoint(float x, float y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.x = checkVal(x);
|
||||
this.y = checkVal(y);
|
||||
}
|
||||
|
||||
/** Returns latitude value at given index */
|
||||
public double getX() {
|
||||
public float getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Returns longitude value at given index */
|
||||
public double getY() {
|
||||
public float getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
|
@ -67,8 +69,8 @@ public final class XYPoint extends XYGeometry {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = Double.hashCode(x);
|
||||
result = 31 * result + Double.hashCode(y);
|
||||
int result = Float.hashCode(x);
|
||||
result = 31 * result + Float.hashCode(y);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,23 +18,25 @@ package org.apache.lucene.geo;
|
|||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.apache.lucene.geo.XYEncodingUtils.checkVal;
|
||||
|
||||
/**
|
||||
* Represents a polygon in cartesian space. You can construct the Polygon directly with {@code float[]}, {@code float[]} x, y arrays
|
||||
* coordinates.
|
||||
*/
|
||||
public final class XYPolygon extends XYGeometry {
|
||||
private final double[] x;
|
||||
private final double[] y;
|
||||
private final float[] x;
|
||||
private final float[] y;
|
||||
private final XYPolygon[] holes;
|
||||
|
||||
/** minimum x of this polygon's bounding box area */
|
||||
public final double minX;
|
||||
public final float minX;
|
||||
/** maximum x of this polygon's bounding box area */
|
||||
public final double maxX;
|
||||
public final float maxX;
|
||||
/** minimum y of this polygon's bounding box area */
|
||||
public final double minY;
|
||||
public final float minY;
|
||||
/** maximum y of this polygon's bounding box area */
|
||||
public final double maxY;
|
||||
public final float maxY;
|
||||
/** winding order of the vertices */
|
||||
private final GeoUtils.WindingOrder windingOrder;
|
||||
|
||||
|
@ -69,26 +71,22 @@ public final class XYPolygon extends XYGeometry {
|
|||
throw new IllegalArgumentException("holes may not contain holes: polygons may not nest.");
|
||||
}
|
||||
}
|
||||
this.x = new double[x.length];
|
||||
this.y = new double[y.length];
|
||||
for (int i = 0; i < x.length; ++i) {
|
||||
this.x[i] = (double)x[i];
|
||||
this.y[i] = (double)y[i];
|
||||
}
|
||||
this.x = x.clone();
|
||||
this.y = y.clone();
|
||||
this.holes = holes.clone();
|
||||
|
||||
// compute bounding box
|
||||
double minX = x[0];
|
||||
double maxX = x[0];
|
||||
double minY = y[0];
|
||||
double maxY = y[0];
|
||||
float minX = checkVal(x[0]);
|
||||
float maxX = x[0];
|
||||
float minY = checkVal(y[0]);
|
||||
float maxY = y[0];
|
||||
|
||||
double windingSum = 0d;
|
||||
final int numPts = x.length - 1;
|
||||
for (int i = 1, j = 0; i < numPts; j = i++) {
|
||||
minX = Math.min(x[i], minX);
|
||||
minX = Math.min(checkVal(x[i]), minX);
|
||||
maxX = Math.max(x[i], maxX);
|
||||
minY = Math.min(y[i], minY);
|
||||
minY = Math.min(checkVal(y[i]), minY);
|
||||
maxY = Math.max(y[i], maxY);
|
||||
// compute signed area
|
||||
windingSum += (x[j] - x[numPts])*(y[i] - y[numPts])
|
||||
|
@ -107,22 +105,22 @@ public final class XYPolygon extends XYGeometry {
|
|||
}
|
||||
|
||||
/** Returns a copy of the internal x array */
|
||||
public double[] getPolyX() {
|
||||
public float[] getPolyX() {
|
||||
return x.clone();
|
||||
}
|
||||
|
||||
/** Returns x value at given index */
|
||||
public double getPolyX(int vertex) {
|
||||
public float getPolyX(int vertex) {
|
||||
return x[vertex];
|
||||
}
|
||||
|
||||
/** Returns a copy of the internal y array */
|
||||
public double[] getPolyY() {
|
||||
public float[] getPolyY() {
|
||||
return y.clone();
|
||||
}
|
||||
|
||||
/** Returns y value at given index */
|
||||
public double getPolyY(int vertex) {
|
||||
public float getPolyY(int vertex) {
|
||||
return y[vertex];
|
||||
}
|
||||
|
||||
|
@ -150,18 +148,6 @@ public final class XYPolygon extends XYGeometry {
|
|||
return Polygon2D.create(this);
|
||||
}
|
||||
|
||||
public String toGeoJSON() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[");
|
||||
sb.append(Polygon.verticesToGeoJSON(y, x));
|
||||
for (XYPolygon hole : holes) {
|
||||
sb.append(",");
|
||||
sb.append(Polygon.verticesToGeoJSON(hole.y, hole.x));
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
|
|
|
@ -16,25 +16,31 @@
|
|||
*/
|
||||
package org.apache.lucene.geo;
|
||||
|
||||
import static org.apache.lucene.geo.XYEncodingUtils.checkVal;
|
||||
|
||||
/** Represents a x/y cartesian rectangle. */
|
||||
public final class XYRectangle extends XYGeometry {
|
||||
/** minimum x value */
|
||||
public final double minX;
|
||||
public final float minX;
|
||||
/** minimum y value */
|
||||
public final double maxX;
|
||||
public final float maxX;
|
||||
/** maximum x value */
|
||||
public final double minY;
|
||||
public final float minY;
|
||||
/** maximum y value */
|
||||
public final double maxY;
|
||||
public final float maxY;
|
||||
|
||||
/** Constructs a bounding box by first validating the provided x and y coordinates */
|
||||
public XYRectangle(double minX, double maxX, double minY, double maxY) {
|
||||
this.minX = minX;
|
||||
this.maxX = maxX;
|
||||
this.minY = minY;
|
||||
this.maxY = maxY;
|
||||
assert minX <= maxX;
|
||||
assert minY <= maxY;
|
||||
public XYRectangle(float minX, float maxX, float minY, float maxY) {
|
||||
if (minX > maxX) {
|
||||
throw new IllegalArgumentException("minX must be lower than maxX, got " + minX + " > " + maxX);
|
||||
}
|
||||
if (minY > maxY) {
|
||||
throw new IllegalArgumentException("minY must be lower than maxY, got " + minY + " > " + maxY);
|
||||
}
|
||||
this.minX = checkVal(minX);
|
||||
this.maxX = checkVal(maxX);
|
||||
this.minY = checkVal(minY);
|
||||
this.maxY = checkVal(maxY);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,10 +55,10 @@ public final class XYRectangle extends XYGeometry {
|
|||
|
||||
XYRectangle rectangle = (XYRectangle) o;
|
||||
|
||||
if (Double.compare(rectangle.minX, minX) != 0) return false;
|
||||
if (Double.compare(rectangle.minY, minY) != 0) return false;
|
||||
if (Double.compare(rectangle.maxX, maxX) != 0) return false;
|
||||
return Double.compare(rectangle.maxY, maxY) == 0;
|
||||
if (Float.compare(rectangle.minX, minX) != 0) return false;
|
||||
if (Float.compare(rectangle.minY, minY) != 0) return false;
|
||||
if (Float.compare(rectangle.maxX, maxX) != 0) return false;
|
||||
return Float.compare(rectangle.maxY, maxY) == 0;
|
||||
|
||||
}
|
||||
|
||||
|
@ -60,13 +66,13 @@ public final class XYRectangle extends XYGeometry {
|
|||
public int hashCode() {
|
||||
int result;
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(minX);
|
||||
temp = Float.floatToIntBits(minX);
|
||||
result = (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(minY);
|
||||
temp = Float.floatToIntBits(minY);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(maxX);
|
||||
temp = Float.floatToIntBits(maxX);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(maxY);
|
||||
temp = Float.floatToIntBits(maxY);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -235,9 +235,6 @@ final class XYRectangle2D implements Component2D {
|
|||
|
||||
/** create a component2D from the provided XY rectangle */
|
||||
static Component2D create(XYRectangle rectangle) {
|
||||
return new XYRectangle2D(XYEncodingUtils.decode(XYEncodingUtils.encode(rectangle.minX)),
|
||||
XYEncodingUtils.decode(XYEncodingUtils.encode(rectangle.maxX)),
|
||||
XYEncodingUtils.decode(XYEncodingUtils.encode(rectangle.minY)),
|
||||
XYEncodingUtils.decode(XYEncodingUtils.encode(rectangle.maxY)));
|
||||
return new XYRectangle2D(rectangle.minX, rectangle.maxX, rectangle.minY, rectangle.maxY);
|
||||
}
|
||||
}
|
|
@ -126,8 +126,8 @@ public abstract class BaseXYShapeTestCase extends BaseShapeTestCase {
|
|||
float[] x = new float[poly.numPoints() - 1];
|
||||
float[] y = new float[x.length];
|
||||
for (int i = 0; i < x.length; ++i) {
|
||||
x[i] = (float) poly.getPolyX(i);
|
||||
y[i] = (float) poly.getPolyY(i);
|
||||
x[i] = poly.getPolyX(i);
|
||||
y[i] = poly.getPolyY(i);
|
||||
}
|
||||
|
||||
return new XYLine(x, y);
|
||||
|
@ -144,8 +144,8 @@ public abstract class BaseXYShapeTestCase extends BaseShapeTestCase {
|
|||
int numPoints = TestUtil.nextInt(random, 1, 20);
|
||||
float[][] points = new float[numPoints][2];
|
||||
for (int i = 0; i < numPoints; i++) {
|
||||
points[i][0] = (float) ShapeTestUtil.nextDouble(random);
|
||||
points[i][1] = (float) ShapeTestUtil.nextDouble(random);
|
||||
points[i][0] = ShapeTestUtil.nextFloat(random);
|
||||
points[i][1] = ShapeTestUtil.nextFloat(random);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
@ -164,22 +164,22 @@ public abstract class BaseXYShapeTestCase extends BaseShapeTestCase {
|
|||
}
|
||||
@Override
|
||||
double quantizeX(double raw) {
|
||||
return decode(encode(raw));
|
||||
return decode(encode((float) raw));
|
||||
}
|
||||
|
||||
@Override
|
||||
double quantizeXCeil(double raw) {
|
||||
return decode(encode(raw));
|
||||
return decode(encode((float) raw));
|
||||
}
|
||||
|
||||
@Override
|
||||
double quantizeY(double raw) {
|
||||
return decode(encode(raw));
|
||||
return decode(encode((float) raw));
|
||||
}
|
||||
|
||||
@Override
|
||||
double quantizeYCeil(double raw) {
|
||||
return decode(encode(raw));
|
||||
return decode(encode((float) raw));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -191,7 +191,7 @@ public abstract class BaseXYShapeTestCase extends BaseShapeTestCase {
|
|||
@Override
|
||||
ShapeField.DecodedTriangle encodeDecodeTriangle(double ax, double ay, boolean ab, double bx, double by, boolean bc, double cx, double cy, boolean ca) {
|
||||
byte[] encoded = new byte[7 * ShapeField.BYTES];
|
||||
ShapeField.encodeTriangle(encoded, encode(ay), encode(ax), ab, encode(by), encode(bx), bc, encode(cy), encode(cx), ca);
|
||||
ShapeField.encodeTriangle(encoded, encode((float) ay), encode((float) ax), ab, encode((float) by), encode((float) bx), bc, encode((float) cy), encode((float) cx), ca);
|
||||
ShapeField.DecodedTriangle triangle = new ShapeField.DecodedTriangle();
|
||||
ShapeField.decodeTriangle(encoded, triangle);
|
||||
return triangle;
|
||||
|
|
|
@ -51,11 +51,11 @@ public class TestXYLineShapeQueries extends BaseXYShapeTestCase {
|
|||
XYLine l = (XYLine) (shapes[i]);
|
||||
if (random.nextBoolean() && l != null) {
|
||||
int v = random.nextInt(l.numPoints() - 1);
|
||||
x[j] = (float)l.getX(v);
|
||||
y[j] = (float)l.getY(v);
|
||||
x[j] = l.getX(v);
|
||||
y[j] = l.getY(v);
|
||||
} else {
|
||||
x[j] = (float)ShapeTestUtil.nextDouble(random);
|
||||
y[j] = (float)ShapeTestUtil.nextDouble(random);
|
||||
x[j] = ShapeTestUtil.nextFloat(random);
|
||||
y[j] = ShapeTestUtil.nextFloat(random);
|
||||
}
|
||||
}
|
||||
return new XYLine(x, y);
|
||||
|
@ -80,7 +80,7 @@ public class TestXYLineShapeQueries extends BaseXYShapeTestCase {
|
|||
|
||||
@Override
|
||||
public boolean testBBoxQuery(double minY, double maxY, double minX, double maxX, Object shape) {
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle((float) minX, (float) maxX, (float) minY, (float) maxY));
|
||||
return testComponentQuery(rectangle2D, shape);
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public class TestXYMultiLineShapeQueries extends BaseXYShapeTestCase {
|
|||
|
||||
@Override
|
||||
public boolean testBBoxQuery(double minY, double maxY, double minX, double maxX, Object shape) {
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle((float) minX, (float) maxX, (float) minY, (float) maxY));
|
||||
return testComponentQuery(rectangle2D, shape);
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ public class TestXYMultiPointShapeQueries extends BaseXYShapeTestCase {
|
|||
|
||||
@Override
|
||||
public boolean testBBoxQuery(double minY, double maxY, double minX, double maxX, Object shape) {
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle((float) minX, (float) maxX, (float) minY, (float) maxY));
|
||||
return testComponentQuery(rectangle2D, shape);
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ public class TestXYMultiPolygonShapeQueries extends BaseXYShapeTestCase {
|
|||
|
||||
@Override
|
||||
public boolean testBBoxQuery(double minY, double maxY, double minX, double maxX, Object shape) {
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle((float) minX, (float) maxX, (float) minY, (float) maxY));
|
||||
return testComponentQuery(rectangle2D, shape);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,8 +53,8 @@ public class TestXYPointShapeQueries extends BaseXYShapeTestCase {
|
|||
x[j] = p.x;
|
||||
y[j] = p.y;
|
||||
} else {
|
||||
x[j] = (float)ShapeTestUtil.nextDouble(random);
|
||||
y[j] = (float)ShapeTestUtil.nextDouble(random);
|
||||
x[j] = ShapeTestUtil.nextFloat(random);
|
||||
y[j] = ShapeTestUtil.nextFloat(random);
|
||||
}
|
||||
}
|
||||
return new XYLine(x, y);
|
||||
|
@ -80,7 +80,7 @@ public class TestXYPointShapeQueries extends BaseXYShapeTestCase {
|
|||
|
||||
@Override
|
||||
public boolean testBBoxQuery(double minY, double maxY, double minX, double maxX, Object shape) {
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle((float) minX, (float) maxX, (float) minY, (float) maxY));
|
||||
return testComponentQuery(rectangle2D, shape);
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ public class TestXYPolygonShapeQueries extends BaseXYShapeTestCase {
|
|||
|
||||
@Override
|
||||
public boolean testBBoxQuery(double minY, double maxY, double minX, double maxX, Object shape) {
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle((float) minX, (float) maxX, (float) minY, (float) maxY));
|
||||
return testComponentQuery(rectangle2D, shape);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,8 +51,8 @@ public class TestXYShape extends LuceneTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
protected Query newRectQuery(String field, double minX, double maxX, double minY, double maxY) {
|
||||
return XYShape.newBoxQuery(field, QueryRelation.INTERSECTS, (float)minX, (float)maxX, (float)minY, (float)maxY);
|
||||
protected Query newRectQuery(String field, float minX, float maxX, float minY, float maxY) {
|
||||
return XYShape.newBoxQuery(field, QueryRelation.INTERSECTS, minX, maxX, minY, maxY);
|
||||
}
|
||||
|
||||
/** test we can search for a point with a standard number of vertices*/
|
||||
|
@ -73,8 +73,8 @@ public class TestXYShape extends LuceneTestCase {
|
|||
float x[] = new float[p.numPoints() - 1];
|
||||
float y[] = new float[p.numPoints() - 1];
|
||||
for (int i = 0; i < x.length; ++i) {
|
||||
x[i] = (float)p.getPolyX(i);
|
||||
y[i] = (float)p.getPolyY(i);
|
||||
x[i] = p.getPolyX(i);
|
||||
y[i] = p.getPolyY(i);
|
||||
}
|
||||
XYLine l = new XYLine(x, y);
|
||||
addLineToDoc(FIELDNAME, document, l);
|
||||
|
@ -85,28 +85,28 @@ public class TestXYShape extends LuceneTestCase {
|
|||
IndexReader reader = writer.getReader();
|
||||
writer.close();
|
||||
IndexSearcher searcher = newSearcher(reader);
|
||||
double minX = Math.min(x[0], x[1]);
|
||||
double minY = Math.min(y[0], y[1]);
|
||||
double maxX = Math.max(x[0], x[1]);
|
||||
double maxY = Math.max(y[0], y[1]);
|
||||
float minX = Math.min(x[0], x[1]);
|
||||
float minY = Math.min(y[0], y[1]);
|
||||
float maxX = Math.max(x[0], x[1]);
|
||||
float maxY = Math.max(y[0], y[1]);
|
||||
Query q = newRectQuery(FIELDNAME, minX, maxX, minY, maxY);
|
||||
assertEquals(2, searcher.count(q));
|
||||
|
||||
// search a disjoint bbox
|
||||
q = newRectQuery(FIELDNAME, p.minX-1d, p.minX+1, p.minY-1d, p.minY+1d);
|
||||
q = newRectQuery(FIELDNAME, p.minX-1f, p.minX + 1f, p.minY - 1f, p.minY + 1f);
|
||||
assertEquals(0, searcher.count(q));
|
||||
|
||||
// search w/ an intersecting polygon
|
||||
q = XYShape.newPolygonQuery(FIELDNAME, QueryRelation.INTERSECTS, new XYPolygon(
|
||||
new float[] {(float)minX, (float)minX, (float)maxX, (float)maxX, (float)minX},
|
||||
new float[] {(float)minY, (float)maxY, (float)maxY, (float)minY, (float)minY}
|
||||
new float[] {minX, minX, maxX, maxX, minX},
|
||||
new float[] {minY, maxY, maxY, minY, minY}
|
||||
));
|
||||
assertEquals(2, searcher.count(q));
|
||||
|
||||
// search w/ an intersecting line
|
||||
q = XYShape.newLineQuery(FIELDNAME, QueryRelation.INTERSECTS, new XYLine(
|
||||
new float[] {(float)minX, (float)minX, (float)maxX, (float)maxX},
|
||||
new float[] {(float)minY, (float)maxY, (float)maxY, (float)minY}
|
||||
new float[] {minX, minX, maxX, maxX},
|
||||
new float[] {minY, maxY, maxY, minY}
|
||||
));
|
||||
assertEquals(2, searcher.count(q));
|
||||
|
||||
|
@ -153,18 +153,18 @@ public class TestXYShape extends LuceneTestCase {
|
|||
q = newRectQuery(FIELDNAME, r1.minX, r1.maxX, r1.minY, r1.maxY);
|
||||
assertEquals(1, searcher.count(q));
|
||||
// r1 contains r2, WITHIN should match
|
||||
q = XYShape.newBoxQuery(FIELDNAME, QueryRelation.WITHIN, (float) r1.minX, (float) r1.maxX, (float) r1.minY, (float) r1.maxY);
|
||||
q = XYShape.newBoxQuery(FIELDNAME, QueryRelation.WITHIN, r1.minX, r1.maxX, r1.minY, r1.maxY);
|
||||
assertEquals(1, searcher.count(q));
|
||||
|
||||
IOUtils.close(reader, dir);
|
||||
}
|
||||
|
||||
private static boolean areBoxDisjoint(XYRectangle r1, XYRectangle r2) {
|
||||
return ((float) r1.minX <= (float) r2.minX && (float) r1.minY <= (float) r2.minY && (float) r1.maxX >= (float) r2.maxX && (float) r1.maxY >= (float) r2.maxY);
|
||||
return ( r1.minX <= r2.minX && r1.minY <= r2.minY && r1.maxX >= r2.maxX && r1.maxY >= r2.maxY);
|
||||
}
|
||||
|
||||
private static XYPolygon toPolygon(XYRectangle r) {
|
||||
return new XYPolygon(new float[]{(float) r.minX, (float) r.maxX, (float) r.maxX, (float) r.minX, (float) r.minX},
|
||||
new float[]{(float) r.minY, (float) r.minY, (float) r.maxY, (float) r.maxY, (float) r.minY});
|
||||
return new XYPolygon(new float[]{ r.minX, r.maxX, r.maxX, r.minX, r.minX},
|
||||
new float[]{ r.minY, r.minY, r.maxY, r.maxY, r.minY});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,12 +26,12 @@ import org.apache.lucene.geo.XYPolygon;
|
|||
public class TestXYShapeEncoding extends BaseShapeEncodingTestCase {
|
||||
@Override
|
||||
protected int encodeX(double x) {
|
||||
return XYEncodingUtils.encode(x);
|
||||
return XYEncodingUtils.encode((float) x);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int encodeY(double y) {
|
||||
return XYEncodingUtils.encode(y);
|
||||
return XYEncodingUtils.encode((float) y);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,12 +46,12 @@ public class TestXYShapeEncoding extends BaseShapeEncodingTestCase {
|
|||
|
||||
@Override
|
||||
protected double nextX() {
|
||||
return ShapeTestUtil.nextDouble(random());
|
||||
return ShapeTestUtil.nextFloat(random());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double nextY() {
|
||||
return ShapeTestUtil.nextDouble(random());
|
||||
return ShapeTestUtil.nextFloat(random());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -40,7 +40,7 @@ public class ShapeTestUtil {
|
|||
// So the poly can cover at most 50% of the earth's surface:
|
||||
double radius = random.nextDouble() * 0.5 * Float.MAX_VALUE + 1.0;
|
||||
try {
|
||||
return createRegularPolygon(nextDouble(random), nextDouble(random), radius, gons);
|
||||
return createRegularPolygon(nextFloat(random), nextFloat(random), radius, gons);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// we tried to cross dateline or pole ... try again
|
||||
}
|
||||
|
@ -57,42 +57,53 @@ public class ShapeTestUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public static XYLine nextLine() {
|
||||
XYPolygon poly = ShapeTestUtil.nextPolygon();
|
||||
float[] x = new float[poly.numPoints() - 1];
|
||||
float[] y = new float[x.length];
|
||||
for (int i = 0; i < x.length; ++i) {
|
||||
x[i] = poly.getPolyX(i);
|
||||
y[i] = poly.getPolyY(i);
|
||||
}
|
||||
return new XYLine(x, y);
|
||||
}
|
||||
|
||||
private static XYPolygon trianglePolygon(XYRectangle box) {
|
||||
final float[] polyX = new float[4];
|
||||
final float[] polyY = new float[4];
|
||||
polyX[0] = (float)box.minX;
|
||||
polyY[0] = (float)box.minY;
|
||||
polyX[1] = (float)box.minX;
|
||||
polyY[1] = (float)box.minY;
|
||||
polyX[2] = (float)box.minX;
|
||||
polyY[2] = (float)box.minY;
|
||||
polyX[3] = (float)box.minX;
|
||||
polyY[3] = (float)box.minY;
|
||||
polyX[0] = box.minX;
|
||||
polyY[0] = box.minY;
|
||||
polyX[1] = box.minX;
|
||||
polyY[1] = box.minY;
|
||||
polyX[2] = box.minX;
|
||||
polyY[2] = box.minY;
|
||||
polyX[3] = box.minX;
|
||||
polyY[3] = box.minY;
|
||||
return new XYPolygon(polyX, polyY);
|
||||
}
|
||||
|
||||
public static XYRectangle nextBox(Random random) {
|
||||
// prevent lines instead of boxes
|
||||
double x0 = nextDouble(random);
|
||||
double x1 = nextDouble(random);
|
||||
float x0 = nextFloat(random);
|
||||
float x1 = nextFloat(random);
|
||||
while (x0 == x1) {
|
||||
x1 = nextDouble(random);
|
||||
x1 = nextFloat(random);
|
||||
}
|
||||
// prevent lines instead of boxes
|
||||
double y0 = nextDouble(random);
|
||||
double y1 = nextDouble(random);
|
||||
float y0 = nextFloat(random);
|
||||
float y1 = nextFloat(random);
|
||||
while (y0 == y1) {
|
||||
y1 = nextDouble(random);
|
||||
y1 = nextFloat(random);
|
||||
}
|
||||
|
||||
if (x1 < x0) {
|
||||
double x = x0;
|
||||
float x = x0;
|
||||
x0 = x1;
|
||||
x1 = x;
|
||||
}
|
||||
|
||||
if (y1 < y0) {
|
||||
double y = y0;
|
||||
float y = y0;
|
||||
y0 = y1;
|
||||
y1 = y;
|
||||
}
|
||||
|
@ -103,16 +114,16 @@ public class ShapeTestUtil {
|
|||
private static XYPolygon boxPolygon(XYRectangle box) {
|
||||
final float[] polyX = new float[5];
|
||||
final float[] polyY = new float[5];
|
||||
polyX[0] = (float)box.minX;
|
||||
polyY[0] = (float)box.minY;
|
||||
polyX[1] = (float)box.minX;
|
||||
polyY[1] = (float)box.minY;
|
||||
polyX[2] = (float)box.minX;
|
||||
polyY[2] = (float)box.minY;
|
||||
polyX[3] = (float)box.minX;
|
||||
polyY[3] = (float)box.minY;
|
||||
polyX[4] = (float)box.minX;
|
||||
polyY[4] = (float)box.minY;
|
||||
polyX[0] = box.minX;
|
||||
polyY[0] = box.minY;
|
||||
polyX[1] = box.minX;
|
||||
polyY[1] = box.minY;
|
||||
polyX[2] = box.minX;
|
||||
polyY[2] = box.minY;
|
||||
polyX[3] = box.minX;
|
||||
polyY[3] = box.minY;
|
||||
polyX[4] = box.minX;
|
||||
polyY[4] = box.minY;
|
||||
return new XYPolygon(polyX, polyY);
|
||||
}
|
||||
|
||||
|
@ -120,8 +131,8 @@ public class ShapeTestUtil {
|
|||
// repeat until we get a poly that doesn't cross dateline:
|
||||
while (true) {
|
||||
//System.out.println("\nPOLY ITER");
|
||||
double centerX = nextDouble(random);
|
||||
double centerY = nextDouble(random);
|
||||
float centerX = nextFloat(random);
|
||||
float centerY = nextFloat(random);
|
||||
double radius = 0.1 + 20 * random.nextDouble();
|
||||
double radiusDelta = random.nextDouble();
|
||||
|
||||
|
@ -135,8 +146,8 @@ public class ShapeTestUtil {
|
|||
break;
|
||||
}
|
||||
double len = radius * (1.0 - radiusDelta + radiusDelta * random.nextDouble());
|
||||
double maxX = StrictMath.min(StrictMath.abs(Float.MAX_VALUE - centerX), StrictMath.abs(-Float.MAX_VALUE - centerX));
|
||||
double maxY = StrictMath.min(StrictMath.abs(Float.MAX_VALUE - centerY), StrictMath.abs(-Float.MAX_VALUE - centerY));
|
||||
float maxX = StrictMath.min(StrictMath.abs(Float.MAX_VALUE - centerX), StrictMath.abs(-Float.MAX_VALUE - centerX));
|
||||
float maxY = StrictMath.min(StrictMath.abs(Float.MAX_VALUE - centerY), StrictMath.abs(-Float.MAX_VALUE - centerY));
|
||||
|
||||
len = StrictMath.min(len, StrictMath.min(maxX, maxY));
|
||||
|
||||
|
@ -195,8 +206,8 @@ public class ShapeTestUtil {
|
|||
return new XYPolygon(result[0], result[1]);
|
||||
}
|
||||
|
||||
public static double nextDouble(Random random) {
|
||||
return BiasedNumbers.randomDoubleBetween(random, -Float.MAX_VALUE, Float.MAX_VALUE);
|
||||
public static float nextFloat(Random random) {
|
||||
return BiasedNumbers.randomFloatBetween(random, -Float.MAX_VALUE, Float.MAX_VALUE);
|
||||
}
|
||||
|
||||
/** Keep it simple, we don't need to take arbitrary Random for geo tests */
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.geo;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
|
||||
public class TestXYLine extends LuceneTestCase {
|
||||
|
||||
/** null x not allowed */
|
||||
public void testLineNullXs() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYLine(null, new float[] { -66, -65, -65, -66, -66 });
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("x must not be null"));
|
||||
}
|
||||
|
||||
/** null y not allowed */
|
||||
public void testPolygonNullYs() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYLine(new float[] {18, 18, 19, 19, 18 }, null);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("y must not be null"));
|
||||
}
|
||||
|
||||
/** needs at least 3 vertices */
|
||||
public void testLineEnoughPoints() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYLine(new float[] {18}, new float[] { -66});
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("at least 2 line points required"));
|
||||
}
|
||||
|
||||
/** lines needs same number of x as y */
|
||||
public void testLinesBogus() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYLine(new float[] { 18, 18, 19, 19 }, new float[] { -66, -65, -65, -66, -66 });
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("must be equal length"));
|
||||
}
|
||||
|
||||
/** line values cannot be NaN */
|
||||
public void testLineNaN() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYLine(new float[] { 18, 18, 19, Float.NaN, 18 }, new float[] { -66, -65, -65, -66, -66 });
|
||||
});
|
||||
assertTrue(expected.getMessage(), expected.getMessage().contains("invalid value NaN"));
|
||||
}
|
||||
|
||||
/** line values cannot be finite */
|
||||
public void testLinePositiveInfinite() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYLine(new float[] { 18, 18, 19, 19, 18 }, new float[] { -66, Float.POSITIVE_INFINITY, -65, -66, -66 });
|
||||
});
|
||||
assertTrue(expected.getMessage(), expected.getMessage().contains("invalid value Inf"));
|
||||
}
|
||||
|
||||
/** line values cannot be finite */
|
||||
public void testLineNegativeInfinite() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYLine(new float[] { 18, 18, 19, 19, 18 }, new float[] { -66, -65, -65, Float.NEGATIVE_INFINITY, -66 });
|
||||
});
|
||||
assertTrue(expected.getMessage(), expected.getMessage().contains("invalid value -Inf"));
|
||||
}
|
||||
|
||||
/** equals and hashcode */
|
||||
public void testEqualsAndHashCode() {
|
||||
XYLine line = ShapeTestUtil.nextLine();
|
||||
XYLine copy = new XYLine(line.getX(), line.getY());
|
||||
assertEquals(line, copy);
|
||||
assertEquals(line.hashCode(), copy.hashCode());
|
||||
XYLine otherLine = ShapeTestUtil.nextLine();
|
||||
if (Arrays.equals(line.getX(), otherLine.getX()) == false ||
|
||||
Arrays.equals(line.getY(), otherLine.getY()) == false) {
|
||||
assertNotEquals(line, otherLine);
|
||||
assertNotEquals(line.hashCode(), otherLine.hashCode());
|
||||
} else {
|
||||
assertEquals(line, otherLine);
|
||||
assertEquals(line.hashCode(), otherLine.hashCode());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.geo;
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
|
||||
public class TestXYPoint extends LuceneTestCase {
|
||||
|
||||
/** point values cannot be NaN */
|
||||
public void testNaN() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYPoint(Float.NaN, 45.23f);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("invalid value NaN"));
|
||||
|
||||
expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYPoint(43.5f, Float.NaN);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("invalid value NaN"));
|
||||
}
|
||||
|
||||
/** point values mist be finite */
|
||||
public void testPositiveInf() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYPoint(Float.POSITIVE_INFINITY, 45.23f);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("invalid value Inf"));
|
||||
|
||||
expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYPoint(43.5f, Float.POSITIVE_INFINITY);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("invalid value Inf"));
|
||||
}
|
||||
|
||||
/** point values mist be finite */
|
||||
public void testNegativeInf() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYPoint(Float.NEGATIVE_INFINITY, 45.23f);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("invalid value -Inf"));
|
||||
|
||||
expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYPoint(43.5f, Float.NEGATIVE_INFINITY);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("invalid value -Inf"));
|
||||
}
|
||||
|
||||
/** equals and hashcode */
|
||||
public void testEqualsAndHashCode() {
|
||||
XYPoint point = new XYPoint(ShapeTestUtil.nextFloat(random()), ShapeTestUtil.nextFloat(random()));
|
||||
XYPoint copy = new XYPoint(point.getX(), point.getY());
|
||||
assertEquals(point, copy);
|
||||
assertEquals(point.hashCode(), copy.hashCode());
|
||||
XYPoint otherPoint = new XYPoint(ShapeTestUtil.nextFloat(random()), ShapeTestUtil.nextFloat(random()));
|
||||
if (point.getX() != otherPoint.getX() || point.getY() != otherPoint.getY()) {
|
||||
assertNotEquals(point, otherPoint);
|
||||
assertNotEquals(point.hashCode(), otherPoint.hashCode());
|
||||
} else {
|
||||
assertEquals(point, otherPoint);
|
||||
assertEquals(point.hashCode(), otherPoint.hashCode());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.geo;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
|
||||
public class TestXYPolygon extends LuceneTestCase {
|
||||
|
||||
/** null x not allowed */
|
||||
public void testPolygonNullPolyLats() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYPolygon(null, new float[] { -66, -65, -65, -66, -66 });
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("x must not be null"));
|
||||
}
|
||||
|
||||
/** null y not allowed */
|
||||
public void testPolygonNullPolyLons() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYPolygon(new float[] {18, 18, 19, 19, 18 }, null);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("y must not be null"));
|
||||
}
|
||||
|
||||
/** polygon needs at least 3 vertices */
|
||||
public void testPolygonLine() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYPolygon(new float[] { 18, 18, 18 }, new float[] { -66, -65, -66 });
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("at least 4 polygon points required"));
|
||||
}
|
||||
|
||||
/** polygon needs same number of latitudes as longitudes */
|
||||
public void testPolygonBogus() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYPolygon(new float[] { 18, 18, 19, 19 }, new float[] { -66, -65, -65, -66, -66 });
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("must be equal length"));
|
||||
}
|
||||
|
||||
/** polygon must be closed */
|
||||
public void testPolygonNotClosed() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYPolygon(new float[] { 18, 18, 19, 19, 19 }, new float[] { -66, -65, -65, -66, -67 });
|
||||
});
|
||||
assertTrue(expected.getMessage(), expected.getMessage().contains("it must close itself"));
|
||||
}
|
||||
|
||||
/** polygon values cannot be NaN */
|
||||
public void testPolygonNaN() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYPolygon(new float[] { 18, 18, 19, Float.NaN, 18 }, new float[] { -66, -65, -65, -66, -66 });
|
||||
});
|
||||
assertTrue(expected.getMessage(), expected.getMessage().contains("invalid value NaN"));
|
||||
}
|
||||
|
||||
/** polygon values cannot be finite */
|
||||
public void testPolygonPositiveInfinite() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYPolygon(new float[] { 18, 18, 19, 19, 18 }, new float[] { -66, Float.POSITIVE_INFINITY, -65, -66, -66 });
|
||||
});
|
||||
assertTrue(expected.getMessage(), expected.getMessage().contains("invalid value Inf"));
|
||||
}
|
||||
|
||||
/** polygon values cannot be finite */
|
||||
public void testPolygonNegativeInfinite() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYPolygon(new float[] { 18, 18, 19, 19, 18 }, new float[] { -66, -65, -65, Float.NEGATIVE_INFINITY, -66 });
|
||||
});
|
||||
assertTrue(expected.getMessage(), expected.getMessage().contains("invalid value -Inf"));
|
||||
}
|
||||
|
||||
/** equals and hashcode */
|
||||
public void testEqualsAndHashCode() {
|
||||
XYPolygon polygon = ShapeTestUtil.nextPolygon();
|
||||
XYPolygon copy = new XYPolygon(polygon.getPolyX(), polygon.getPolyY(), polygon.getHoles());
|
||||
assertEquals(polygon, copy);
|
||||
assertEquals(polygon.hashCode(), copy.hashCode());
|
||||
XYPolygon otherPolygon = ShapeTestUtil.nextPolygon();
|
||||
if (Arrays.equals(polygon.getPolyX(), otherPolygon.getPolyX()) == false ||
|
||||
Arrays.equals(polygon.getPolyY(), otherPolygon.getPolyY()) == false ||
|
||||
Arrays.equals(polygon.getHoles(), otherPolygon.getHoles()) == false) {
|
||||
assertNotEquals(polygon, otherPolygon);
|
||||
assertNotEquals(polygon.hashCode(), otherPolygon.hashCode());
|
||||
} else {
|
||||
assertEquals(polygon, otherPolygon);
|
||||
assertEquals(polygon.hashCode(), otherPolygon.hashCode());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.lucene.geo;
|
||||
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
|
||||
public class TestXYRectangle extends LuceneTestCase {
|
||||
|
||||
/** maxX must be gte minX */
|
||||
public void tesInvalidMinMaxX() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYRectangle(5, 4, 3 ,4);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("5 > 4"));
|
||||
}
|
||||
|
||||
/** maxY must be gte minY */
|
||||
public void tesInvalidMinMaxY() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYRectangle(4, 5, 5 ,4);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("5 > 4"));
|
||||
}
|
||||
|
||||
/** rectangle values cannot be NaN */
|
||||
public void testNaN() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYRectangle(Float.NaN, 4, 3 ,4);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("invalid value NaN"));
|
||||
|
||||
expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYRectangle(3, Float.NaN, 3 ,4);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("invalid value NaN"));
|
||||
|
||||
expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYRectangle(3, 4, Float.NaN ,4);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("invalid value NaN"));
|
||||
|
||||
expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYRectangle(3, 4, 3 , Float.NaN);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("invalid value NaN"));
|
||||
}
|
||||
|
||||
/** rectangle values must be finite */
|
||||
public void testPositiveInf() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYRectangle(3, Float.POSITIVE_INFINITY, 3 ,4);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("invalid value Inf"));
|
||||
|
||||
expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYRectangle(3, 4, 3 , Float.POSITIVE_INFINITY);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("invalid value Inf"));
|
||||
}
|
||||
|
||||
/** rectangle values must be finite */
|
||||
public void testNegativeInf() {
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYRectangle(Float.NEGATIVE_INFINITY, 4, 3 ,4);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("invalid value -Inf"));
|
||||
|
||||
expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new XYRectangle(3, 4, Float.NEGATIVE_INFINITY ,4);
|
||||
});
|
||||
assertTrue(expected.getMessage().contains("invalid value -Inf"));
|
||||
}
|
||||
|
||||
/** equals and hashcode */
|
||||
public void testEqualsAndHashCode() {
|
||||
XYRectangle rectangle = ShapeTestUtil.nextBox(random());
|
||||
XYRectangle copy = new XYRectangle(rectangle.minX, rectangle.maxX, rectangle.minY, rectangle.maxY);
|
||||
assertEquals(rectangle, copy);
|
||||
assertEquals(rectangle.hashCode(), copy.hashCode());
|
||||
XYRectangle otherRectangle = ShapeTestUtil.nextBox(random());
|
||||
if (rectangle.minX != otherRectangle.minX || rectangle.maxX != otherRectangle.maxX ||
|
||||
rectangle.minY != otherRectangle.minY || rectangle.maxY != otherRectangle.maxY) {
|
||||
assertNotEquals(rectangle, otherRectangle);
|
||||
assertNotEquals(rectangle.hashCode(), otherRectangle.hashCode());
|
||||
} else {
|
||||
assertEquals(rectangle, otherRectangle);
|
||||
assertEquals(rectangle.hashCode(), otherRectangle.hashCode());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -26,7 +26,7 @@ import org.apache.lucene.util.LuceneTestCase;
|
|||
public class TestXYRectangle2D extends LuceneTestCase {
|
||||
|
||||
public void testTriangleDisjoint() {
|
||||
XYRectangle rectangle = new XYRectangle(0d, 1d, 0d, 1d);
|
||||
XYRectangle rectangle = new XYRectangle(0f, 1f, 0f, 1f);
|
||||
Component2D rectangle2D = XYRectangle2D.create(rectangle);
|
||||
float ax = 4f;
|
||||
float ay = 4f;
|
||||
|
@ -38,7 +38,7 @@ public class TestXYRectangle2D extends LuceneTestCase {
|
|||
}
|
||||
|
||||
public void testTriangleIntersects() {
|
||||
XYRectangle rectangle = new XYRectangle(0d, 1d, 0d, 1d);
|
||||
XYRectangle rectangle = new XYRectangle(0f, 1f, 0f, 1f);
|
||||
Component2D rectangle2D = XYRectangle2D.create(rectangle);
|
||||
float ax = 0.5f;
|
||||
float ay = 0.5f;
|
||||
|
@ -66,12 +66,12 @@ public class TestXYRectangle2D extends LuceneTestCase {
|
|||
XYRectangle rectangle = ShapeTestUtil.nextBox(random);
|
||||
Component2D rectangle2D = XYRectangle2D.create(rectangle);
|
||||
for (int i =0; i < 100; i++) {
|
||||
float ax = (float) ShapeTestUtil.nextDouble(random);
|
||||
float ay = (float) ShapeTestUtil.nextDouble(random);
|
||||
float bx = (float) ShapeTestUtil.nextDouble(random);
|
||||
float by = (float) ShapeTestUtil.nextDouble(random);
|
||||
float cx = (float) ShapeTestUtil.nextDouble(random);
|
||||
float cy = (float) ShapeTestUtil.nextDouble(random);
|
||||
float ax = ShapeTestUtil.nextFloat(random);
|
||||
float ay = ShapeTestUtil.nextFloat(random);
|
||||
float bx = ShapeTestUtil.nextFloat(random);
|
||||
float by = ShapeTestUtil.nextFloat(random);
|
||||
float cx = ShapeTestUtil.nextFloat(random);
|
||||
float cy = ShapeTestUtil.nextFloat(random);
|
||||
|
||||
float tMinX = StrictMath.min(StrictMath.min(ax, bx), cx);
|
||||
float tMaxX = StrictMath.max(StrictMath.max(ax, bx), cx);
|
||||
|
|
Loading…
Reference in New Issue