You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2016/03/22 17:12:23 UTC
[2/3] lucene-solr:branch_6_0: LUCENE-7128: clean up new geo APIs to
consistently take lat before lon, make methods private when possible,
use lat/lon instead of y/x naming, remove unused code
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/09013e09/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoProjectionUtils.java
----------------------------------------------------------------------
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoProjectionUtils.java b/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoProjectionUtils.java
index 12d1350..61aa09f 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoProjectionUtils.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoProjectionUtils.java
@@ -69,83 +69,14 @@ public class GeoProjectionUtils {
}
/**
- * Converts from geocentric earth-centered earth-fixed to geodesic lat/lon/alt
- * @param x Cartesian x coordinate
- * @param y Cartesian y coordinate
- * @param z Cartesian z coordinate
- * @param lla 0: longitude 1: latitude: 2: altitude
- * @return double array as 0: longitude 1: latitude 2: altitude
- */
- public static final double[] ecfToLLA(final double x, final double y, final double z, double[] lla) {
- boolean atPole = false;
- final double ad_c = 1.0026000D;
- final double cos67P5 = 0.38268343236508977D;
-
- if (lla == null) {
- lla = new double[3];
- }
-
- if (x != 0.0) {
- lla[0] = StrictMath.atan2(y,x);
- } else {
- if (y > 0) {
- lla[0] = PIO2;
- } else if (y < 0) {
- lla[0] = -PIO2;
- } else {
- atPole = true;
- lla[0] = 0.0D;
- if (z > 0.0) {
- lla[1] = PIO2;
- } else if (z < 0.0) {
- lla[1] = -PIO2;
- } else {
- lla[1] = PIO2;
- lla[2] = -SEMIMINOR_AXIS;
- return lla;
- }
- }
- }
-
- final double w2 = x*x + y*y;
- final double w = StrictMath.sqrt(w2);
- final double t0 = z * ad_c;
- final double s0 = StrictMath.sqrt(t0 * t0 + w2);
- final double sinB0 = t0 / s0;
- final double cosB0 = w / s0;
- final double sin3B0 = sinB0 * sinB0 * sinB0;
- final double t1 = z + SEMIMINOR_AXIS * EP2 * sin3B0;
- final double sum = w - SEMIMAJOR_AXIS * E2 * cosB0 * cosB0 * cosB0;
- final double s1 = StrictMath.sqrt(t1 * t1 + sum * sum);
- final double sinP1 = t1 / s1;
- final double cosP1 = sum / s1;
- final double rn = SEMIMAJOR_AXIS / StrictMath.sqrt(1.0D - E2 * sinP1 * sinP1);
-
- if (cosP1 >= cos67P5) {
- lla[2] = w / cosP1 - rn;
- } else if (cosP1 <= -cos67P5) {
- lla[2] = w / -cosP1 - rn;
- } else {
- lla[2] = z / sinP1 + rn * (E2 - 1.0);
- }
- if (!atPole) {
- lla[1] = StrictMath.atan(sinP1/cosP1);
- }
- lla[0] = TO_DEGREES * lla[0];
- lla[1] = TO_DEGREES * lla[1];
-
- return lla;
- }
-
- /**
- * Converts from geodesic lon lat alt to geocentric earth-centered earth-fixed
- * @param lon geodesic longitude
+ * Converts from geodesic lat lon alt to geocentric earth-centered earth-fixed
* @param lat geodesic latitude
+ * @param lon geodesic longitude
* @param alt geodesic altitude
* @param ecf reusable earth-centered earth-fixed result
* @return either a new ecef array or the reusable ecf parameter
*/
- public static final double[] llaToECF(double lon, double lat, double alt, double[] ecf) {
+ public static final double[] llaToECF(double lat, double lon, double alt, double[] ecf) {
lon = TO_RADIANS * lon;
lat = TO_RADIANS * lat;
@@ -177,261 +108,23 @@ public class GeoProjectionUtils {
}
/**
- * Converts from lat lon alt (in degrees) to East North Up right-hand coordinate system
- * @param lon longitude in degrees
- * @param lat latitude in degrees
- * @param alt altitude in meters
- * @param centerLon reference point longitude in degrees
- * @param centerLat reference point latitude in degrees
- * @param centerAlt reference point altitude in meters
- * @param enu result east, north, up coordinate
- * @return east, north, up coordinate
- */
- public static double[] llaToENU(final double lon, final double lat, final double alt, double centerLon,
- double centerLat, final double centerAlt, double[] enu) {
- if (enu == null) {
- enu = new double[3];
- }
-
- // convert point to ecf coordinates
- final double[] ecf = llaToECF(lon, lat, alt, null);
-
- // convert from ecf to enu
- return ecfToENU(ecf[0], ecf[1], ecf[2], centerLon, centerLat, centerAlt, enu);
- }
-
- /**
- * Converts from East North Up right-hand rule to lat lon alt in degrees
- * @param x easting (in meters)
- * @param y northing (in meters)
- * @param z up (in meters)
- * @param centerLon reference point longitude (in degrees)
- * @param centerLat reference point latitude (in degrees)
- * @param centerAlt reference point altitude (in meters)
- * @param lla resulting lat, lon, alt point (in degrees)
- * @return lat, lon, alt point (in degrees)
- */
- public static double[] enuToLLA(final double x, final double y, final double z, final double centerLon,
- final double centerLat, final double centerAlt, double[] lla) {
- // convert enuToECF
- if (lla == null) {
- lla = new double[3];
- }
-
- // convert enuToECF, storing intermediate result in lla
- lla = enuToECF(x, y, z, centerLon, centerLat, centerAlt, lla);
-
- // convert ecf to LLA
- return ecfToLLA(lla[0], lla[1], lla[2], lla);
- }
-
- /**
- * Convert from Earth-Centered-Fixed to Easting, Northing, Up Right Hand System
- * @param x ECF X coordinate (in meters)
- * @param y ECF Y coordinate (in meters)
- * @param z ECF Z coordinate (in meters)
- * @param centerLon ENU origin longitude (in degrees)
- * @param centerLat ENU origin latitude (in degrees)
- * @param centerAlt ENU altitude (in meters)
- * @param enu reusable enu result
- * @return Easting, Northing, Up coordinate
- */
- public static double[] ecfToENU(double x, double y, double z, final double centerLon,
- final double centerLat, final double centerAlt, double[] enu) {
- if (enu == null) {
- enu = new double[3];
- }
-
- // create rotation matrix and rotate to enu orientation
- final double[][] phi = createPhiTransform(centerLon, centerLat, null);
-
- // convert origin to ENU
- final double[] originECF = llaToECF(centerLon, centerLat, centerAlt, null);
- final double[] originENU = new double[3];
- originENU[0] = ((phi[0][0] * originECF[0]) + (phi[0][1] * originECF[1]) + (phi[0][2] * originECF[2]));
- originENU[1] = ((phi[1][0] * originECF[0]) + (phi[1][1] * originECF[1]) + (phi[1][2] * originECF[2]));
- originENU[2] = ((phi[2][0] * originECF[0]) + (phi[2][1] * originECF[1]) + (phi[2][2] * originECF[2]));
-
- // rotate then translate
- enu[0] = ((phi[0][0] * x) + (phi[0][1] * y) + (phi[0][2] * z)) - originENU[0];
- enu[1] = ((phi[1][0] * x) + (phi[1][1] * y) + (phi[1][2] * z)) - originENU[1];
- enu[2] = ((phi[2][0] * x) + (phi[2][1] * y) + (phi[2][2] * z)) - originENU[2];
-
- return enu;
- }
-
- /**
- * Convert from Easting, Northing, Up Right-Handed system to Earth Centered Fixed system
- * @param x ENU x coordinate (in meters)
- * @param y ENU y coordinate (in meters)
- * @param z ENU z coordinate (in meters)
- * @param centerLon ENU origin longitude (in degrees)
- * @param centerLat ENU origin latitude (in degrees)
- * @param centerAlt ENU origin altitude (in meters)
- * @param ecf reusable ecf result
- * @return ecf result coordinate
- */
- public static double[] enuToECF(final double x, final double y, final double z, double centerLon,
- double centerLat, final double centerAlt, double[] ecf) {
- if (ecf == null) {
- ecf = new double[3];
- }
-
- double[][] phi = createTransposedPhiTransform(centerLon, centerLat, null);
- double[] ecfOrigin = llaToECF(centerLon, centerLat, centerAlt, null);
-
- // rotate and translate
- ecf[0] = (phi[0][0]*x + phi[0][1]*y + phi[0][2]*z) + ecfOrigin[0];
- ecf[1] = (phi[1][0]*x + phi[1][1]*y + phi[1][2]*z) + ecfOrigin[1];
- ecf[2] = (phi[2][0]*x + phi[2][1]*y + phi[2][2]*z) + ecfOrigin[2];
-
- return ecf;
- }
-
- /**
- * Create the rotation matrix for converting Earth Centered Fixed to Easting Northing Up
- * @param originLon ENU origin longitude (in degrees)
- * @param originLat ENU origin latitude (in degrees)
- * @param phiMatrix reusable phi matrix result
- * @return phi rotation matrix
- */
- private static double[][] createPhiTransform(double originLon, double originLat, double[][] phiMatrix) {
-
- if (phiMatrix == null) {
- phiMatrix = new double[3][3];
- }
-
- originLon = TO_RADIANS * originLon;
- originLat = TO_RADIANS * originLat;
-
- final double sLon = sloppySin(originLon);
- final double cLon = cos(originLon);
- final double sLat = sloppySin(originLat);
- final double cLat = cos(originLat);
-
- phiMatrix[0][0] = -sLon;
- phiMatrix[0][1] = cLon;
- phiMatrix[0][2] = 0.0D;
- phiMatrix[1][0] = -sLat * cLon;
- phiMatrix[1][1] = -sLat * sLon;
- phiMatrix[1][2] = cLat;
- phiMatrix[2][0] = cLat * cLon;
- phiMatrix[2][1] = cLat * sLon;
- phiMatrix[2][2] = sLat;
-
- return phiMatrix;
- }
-
- /**
- * Create the transposed rotation matrix for converting Easting Northing Up coordinates to Earth Centered Fixed
- * @param originLon ENU origin longitude (in degrees)
- * @param originLat ENU origin latitude (in degrees)
- * @param phiMatrix reusable phi rotation matrix result
- * @return transposed phi rotation matrix
- */
- private static double[][] createTransposedPhiTransform(double originLon, double originLat, double[][] phiMatrix) {
-
- if (phiMatrix == null) {
- phiMatrix = new double[3][3];
- }
-
- originLon = TO_RADIANS * originLon;
- originLat = TO_RADIANS * originLat;
-
- final double sLat = sloppySin(originLat);
- final double cLat = cos(originLat);
- final double sLon = sloppySin(originLon);
- final double cLon = cos(originLon);
-
- phiMatrix[0][0] = -sLon;
- phiMatrix[1][0] = cLon;
- phiMatrix[2][0] = 0.0D;
- phiMatrix[0][1] = -sLat * cLon;
- phiMatrix[1][1] = -sLat * sLon;
- phiMatrix[2][1] = cLat;
- phiMatrix[0][2] = cLat * cLon;
- phiMatrix[1][2] = cLat * sLon;
- phiMatrix[2][2] = sLat;
-
- return phiMatrix;
- }
-
- /**
- * Finds a point along a bearing from a given lon,lat geolocation using vincenty's distance formula
+ * Finds a point along a bearing from a given lat,lon geolocation using great circle arc
*
- * @param lon origin longitude in degrees
* @param lat origin latitude in degrees
- * @param bearing azimuthal bearing in degrees
- * @param dist distance in meters
- * @param pt resulting point
- * @return the point along a bearing at a given distance in meters
- */
- public static final double[] pointFromLonLatBearingVincenty(double lon, double lat, double bearing, double dist, double[] pt) {
-
- if (pt == null) {
- pt = new double[2];
- }
-
- final double alpha1 = TO_RADIANS * bearing;
- final double cosA1 = cos(alpha1);
- final double sinA1 = sloppySin(alpha1);
- final double tanU1 = (1-FLATTENING) * sloppyTan(TO_RADIANS * lat);
- final double cosU1 = 1 / StrictMath.sqrt((1+tanU1*tanU1));
- final double sinU1 = tanU1*cosU1;
- final double sig1 = StrictMath.atan2(tanU1, cosA1);
- final double sinAlpha = cosU1 * sinA1;
- final double cosSqAlpha = 1 - sinAlpha*sinAlpha;
- final double uSq = cosSqAlpha * EP2;
- final double A = 1 + uSq/16384D*(4096D + uSq * (-768D + uSq * (320D - 175D*uSq)));
- final double B = uSq/1024D * (256D + uSq * (-128D + uSq * (74D - 47D * uSq)));
-
- double sigma = dist / (SEMIMINOR_AXIS*A);
- double sigmaP;
- double sinSigma, cosSigma, cos2SigmaM, deltaSigma;
-
- do {
- cos2SigmaM = cos(2*sig1 + sigma);
- sinSigma = sloppySin(sigma);
- cosSigma = cos(sigma);
-
- deltaSigma = B * sinSigma * (cos2SigmaM + (B/4D) * (cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
- (B/6) * cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
- sigmaP = sigma;
- sigma = dist / (SEMIMINOR_AXIS*A) + deltaSigma;
- } while (StrictMath.abs(sigma-sigmaP) > 1E-12);
-
- final double tmp = sinU1*sinSigma - cosU1*cosSigma*cosA1;
- final double lat2 = StrictMath.atan2(sinU1*cosSigma + cosU1*sinSigma*cosA1,
- (1-FLATTENING) * StrictMath.sqrt(sinAlpha*sinAlpha + tmp*tmp));
- final double lambda = StrictMath.atan2(sinSigma*sinA1, cosU1*cosSigma - sinU1*sinSigma*cosA1);
- final double c = FLATTENING/16 * cosSqAlpha * (4 + FLATTENING * (4 - 3 * cosSqAlpha));
-
- final double lam = lambda - (1-c) * FLATTENING * sinAlpha *
- (sigma + c * sinSigma * (cos2SigmaM + c * cosSigma * (-1 + 2* cos2SigmaM*cos2SigmaM)));
- pt[0] = normalizeLon(lon + TO_DEGREES * lam);
- pt[1] = normalizeLat(TO_DEGREES * lat2);
-
- return pt;
- }
-
- /**
- * Finds a point along a bearing from a given lon,lat geolocation using great circle arc
- *
* @param lon origin longitude in degrees
- * @param lat origin latitude in degrees
* @param bearing azimuthal bearing in degrees
* @param dist distance in meters
* @param pt resulting point
* @return the point along a bearing at a given distance in meters
*/
- public static final double[] pointFromLonLatBearingGreatCircle(double lon, double lat, double bearing, double dist, double[] pt) {
+ public static final double[] pointFromLonLatBearingGreatCircle(double lat, double lon, double bearing, double dist, double[] pt) {
if (pt == null) {
pt = new double[2];
}
- lon *= TO_RADIANS;
lat *= TO_RADIANS;
+ lon *= TO_RADIANS;
bearing *= TO_RADIANS;
final double cLat = cos(lat);
@@ -447,14 +140,14 @@ public class GeoProjectionUtils {
}
/**
- * Finds the bearing (in degrees) between 2 geo points (lon, lat) using great circle arc
- * @param lon1 first point longitude in degrees
+ * Finds the bearing (in degrees) between 2 geo points (lat, lon) using great circle arc
* @param lat1 first point latitude in degrees
- * @param lon2 second point longitude in degrees
+ * @param lon1 first point longitude in degrees
* @param lat2 second point latitude in degrees
+ * @param lon2 second point longitude in degrees
* @return the bearing (in degrees) between the two provided points
*/
- public static double bearingGreatCircle(double lon1, double lat1, double lon2, double lat2) {
+ public static double bearingGreatCircle(double lat1, double lon1, double lat2, double lon2) {
double dLon = (lon2 - lon1) * TO_RADIANS;
lat2 *= TO_RADIANS;
lat1 *= TO_RADIANS;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/09013e09/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRect.java
----------------------------------------------------------------------
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRect.java b/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRect.java
index e147351..8d947b4 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRect.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRect.java
@@ -18,19 +18,19 @@ package org.apache.lucene.spatial.util;
/** Represents a lat/lon rectangle. */
public class GeoRect {
- /** minimum longitude value (in degrees) */
- public final double minLon;
- /** minimum latitude value (in degrees) */
- public final double maxLon;
/** maximum longitude value (in degrees) */
public final double minLat;
+ /** minimum longitude value (in degrees) */
+ public final double minLon;
/** maximum latitude value (in degrees) */
public final double maxLat;
+ /** minimum latitude value (in degrees) */
+ public final double maxLon;
/**
* Constructs a bounding box by first validating the provided latitude and longitude coordinates
*/
- public GeoRect(double minLon, double maxLon, double minLat, double maxLat) {
+ public GeoRect(double minLat, double maxLat, double minLon, double maxLon) {
if (GeoUtils.isValidLon(minLon) == false) {
throw new IllegalArgumentException("invalid minLon " + minLon);
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/09013e09/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRelationUtils.java
----------------------------------------------------------------------
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRelationUtils.java b/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRelationUtils.java
index e40b91a..4a31202 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRelationUtils.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRelationUtils.java
@@ -28,13 +28,14 @@ public class GeoRelationUtils {
}
/**
- * Determine if a bbox (defined by minLon, minLat, maxLon, maxLat) contains the provided point (defined by lon, lat)
+ * Determine if a bbox (defined by minLat, maxLat, minLon, maxLon) contains the provided point (defined by lat, lon)
* NOTE: this is a basic method that does not handle dateline or pole crossing. Unwrapping must be done before
* calling this method.
*/
- public static boolean pointInRectPrecise(final double lon, final double lat, final double minLon,
- final double minLat, final double maxLon, final double maxLat) {
- return lon >= minLon && lon <= maxLon && lat >= minLat && lat <= maxLat;
+ public static boolean pointInRectPrecise(final double lat, final double lon,
+ final double minLat, final double maxLat,
+ final double minLon, final double maxLon) {
+ return lat >= minLat && lat <= maxLat && lon >= minLon && lon <= maxLon;
}
/**
@@ -46,17 +47,17 @@ public class GeoRelationUtils {
*
* NOTE: Requires polygon point (x,y) order either clockwise or counter-clockwise
*/
- public static boolean pointInPolygon(double[] x, double[] y, double lat, double lon) {
- assert x.length == y.length;
+ public static boolean pointInPolygon(double[] polyLats, double[] polyLons, double lat, double lon) {
+ assert polyLats.length == polyLons.length;
boolean inPoly = false;
/**
* Note: This is using a euclidean coordinate system which could result in
* upwards of 110KM error at the equator.
* TODO convert coordinates to cylindrical projection (e.g. mercator)
*/
- for (int i = 1; i < x.length; i++) {
- if (x[i] <= lon && x[i-1] >= lon || x[i-1] <= lon && x[i] >= lon) {
- if (y[i] + (lon - x[i]) / (x[i-1] - x[i]) * (y[i-1] - y[i]) <= lat) {
+ for (int i = 1; i < polyLats.length; i++) {
+ if (polyLons[i] <= lon && polyLons[i-1] >= lon || polyLons[i-1] <= lon && polyLons[i] >= lon) {
+ if (polyLats[i] + (lon - polyLons[i]) / (polyLons[i-1] - polyLons[i]) * (polyLats[i-1] - polyLats[i]) <= lat) {
inPoly = !inPoly;
}
}
@@ -71,42 +72,34 @@ public class GeoRelationUtils {
/**
* Computes whether two rectangles are disjoint
*/
- public static boolean rectDisjoint(final double aMinX, final double aMinY, final double aMaxX, final double aMaxY,
- final double bMinX, final double bMinY, final double bMaxX, final double bMaxY) {
- return (aMaxX < bMinX || aMinX > bMaxX || aMaxY < bMinY || aMinY > bMaxY);
+ private static boolean rectDisjoint(final double aMinLat, final double aMaxLat, final double aMinLon, final double aMaxLon,
+ final double bMinLat, final double bMaxLat, final double bMinLon, final double bMaxLon) {
+ return (aMaxLon < bMinLon || aMinLon > bMaxLon || aMaxLat < bMinLat || aMinLat > bMaxLat);
}
/**
* Computes whether the first (a) rectangle is wholly within another (b) rectangle (shared boundaries allowed)
*/
- public static boolean rectWithin(final double aMinX, final double aMinY, final double aMaxX, final double aMaxY,
- final double bMinX, final double bMinY, final double bMaxX, final double bMaxY) {
- return !(aMinX < bMinX || aMinY < bMinY || aMaxX > bMaxX || aMaxY > bMaxY);
+ public static boolean rectWithin(final double aMinLat, final double aMaxLat, final double aMinLon, final double aMaxLon,
+ final double bMinLat, final double bMaxLat, final double bMinLon, final double bMaxLon) {
+ return !(aMinLon < bMinLon || aMinLat < bMinLat || aMaxLon > bMaxLon || aMaxLat > bMaxLat);
}
/**
* Computes whether two rectangles cross
*/
- public static boolean rectCrosses(final double aMinX, final double aMinY, final double aMaxX, final double aMaxY,
- final double bMinX, final double bMinY, final double bMaxX, final double bMaxY) {
- return !(rectDisjoint(aMinX, aMinY, aMaxX, aMaxY, bMinX, bMinY, bMaxX, bMaxY) ||
- rectWithin(aMinX, aMinY, aMaxX, aMaxY, bMinX, bMinY, bMaxX, bMaxY));
- }
-
- /**
- * Computes whether rectangle a contains rectangle b (touching allowed)
- */
- public static boolean rectContains(final double aMinX, final double aMinY, final double aMaxX, final double aMaxY,
- final double bMinX, final double bMinY, final double bMaxX, final double bMaxY) {
- return !(bMinX < aMinX || bMinY < aMinY || bMaxX > aMaxX || bMaxY > aMaxY);
+ public static boolean rectCrosses(final double aMinLat, final double aMaxLat, final double aMinLon, final double aMaxLon,
+ final double bMinLat, final double bMaxLat, final double bMinLon, final double bMaxLon) {
+ return !(rectDisjoint(aMinLat, aMaxLat, aMinLon, aMaxLon, bMinLat, bMaxLat, bMinLon, bMaxLon) ||
+ rectWithin(aMinLat, aMaxLat, aMinLon, aMaxLon, bMinLat, bMaxLat, bMinLon, bMaxLon));
}
/**
* Computes whether a rectangle intersects another rectangle (crosses, within, touching, etc)
*/
- public static boolean rectIntersects(final double aMinX, final double aMinY, final double aMaxX, final double aMaxY,
- final double bMinX, final double bMinY, final double bMaxX, final double bMaxY) {
- return !((aMaxX < bMinX || aMinX > bMaxX || aMaxY < bMinY || aMinY > bMaxY) );
+ public static boolean rectIntersects(final double aMinLat, final double aMaxLat, final double aMinLon, final double aMaxLon,
+ final double bMinLat, final double bMaxLat, final double bMinLon, final double bMaxLon) {
+ return !((aMaxLon < bMinLon || aMinLon > bMaxLon || aMaxLat < bMinLat || aMinLat > bMaxLat));
}
/////////////////////////
@@ -116,33 +109,35 @@ public class GeoRelationUtils {
/**
* Convenience method for accurately computing whether a rectangle crosses a poly
*/
- public static boolean rectCrossesPolyPrecise(final double rMinX, final double rMinY, final double rMaxX,
- final double rMaxY, final double[] shapeX, final double[] shapeY,
- final double sMinX, final double sMinY, final double sMaxX,
- final double sMaxY) {
+ public static boolean rectCrossesPolyPrecise(final double rMinLat, final double rMaxLat,
+ final double rMinLon, final double rMaxLon,
+ final double[] shapeLat, final double[] shapeLon,
+ final double sMinLat, final double sMaxLat,
+ final double sMinLon, final double sMaxLon) {
// short-circuit: if the bounding boxes are disjoint then the shape does not cross
- if (rectDisjoint(rMinX, rMinY, rMaxX, rMaxY, sMinX, sMinY, sMaxX, sMaxY)) {
+ if (rectDisjoint(rMinLat, rMaxLat, rMinLon, rMaxLon, sMinLat, sMaxLat, sMinLon, sMaxLon)) {
return false;
}
- return rectCrossesPoly(rMinX, rMinY, rMaxX, rMaxY, shapeX, shapeY);
+ return rectCrossesPoly(rMinLat, rMaxLat, rMinLon, rMaxLon, shapeLat, shapeLon);
}
/**
* Compute whether a rectangle crosses a shape. (touching not allowed) Includes a flag for approximating the
* relation.
*/
- public static boolean rectCrossesPolyApprox(final double rMinX, final double rMinY, final double rMaxX,
- final double rMaxY, final double[] shapeX, final double[] shapeY,
- final double sMinX, final double sMinY, final double sMaxX,
- final double sMaxY) {
+ public static boolean rectCrossesPolyApprox(final double rMinLat, final double rMaxLat,
+ final double rMinLon, final double rMaxLon,
+ final double[] shapeLat, final double[] shapeLon,
+ final double sMinLat, final double sMaxLat,
+ final double sMinLon, final double sMaxLon) {
// short-circuit: if the bounding boxes are disjoint then the shape does not cross
- if (rectDisjoint(rMinX, rMinY, rMaxX, rMaxY, sMinX, sMinY, sMaxX, sMaxY)) {
+ if (rectDisjoint(rMinLat, rMaxLat, rMinLon, rMaxLon, sMinLat, sMaxLat, sMinLon, sMaxLon)) {
return false;
}
- final int polyLength = shapeX.length-1;
+ final int polyLength = shapeLon.length-1;
for (short p=0; p<polyLength; ++p) {
- if (lineCrossesRect(shapeX[p], shapeY[p], shapeX[p+1], shapeY[p+1], rMinX, rMinY, rMaxX, rMaxY) == true) {
+ if (lineCrossesRect(shapeLat[p], shapeLon[p], shapeLat[p+1], shapeLon[p+1], rMinLat, rMaxLat, rMinLon, rMaxLon) == true) {
return true;
}
}
@@ -152,10 +147,11 @@ public class GeoRelationUtils {
/**
* Accurately compute (within restrictions of cartesian decimal degrees) whether a rectangle crosses a polygon
*/
- private static boolean rectCrossesPoly(final double rMinX, final double rMinY, final double rMaxX,
- final double rMaxY, final double[] shapeX, final double[] shapeY) {
- final double[][] bbox = new double[][] { {rMinX, rMinY}, {rMaxX, rMinY}, {rMaxX, rMaxY}, {rMinX, rMaxY}, {rMinX, rMinY} };
- final int polyLength = shapeX.length-1;
+ private static boolean rectCrossesPoly(final double rMinLat, final double rMaxLat,
+ final double rMinLon, final double rMaxLon,
+ final double[] shapeLats, final double[] shapeLons) {
+ final double[][] bbox = new double[][] { {rMinLon, rMinLat}, {rMaxLon, rMinLat}, {rMaxLon, rMaxLat}, {rMinLon, rMaxLat}, {rMinLon, rMinLat} };
+ final int polyLength = shapeLons.length-1;
double d, s, t, a1, b1, c1, a2, b2, c2;
double x00, y00, x01, y01, x10, y10, x11, y11;
@@ -165,23 +161,23 @@ public class GeoRelationUtils {
b1 = bbox[b][0]-bbox[b+1][0];
c1 = a1*bbox[b+1][0] + b1*bbox[b+1][1];
for (int p=0; p<polyLength; ++p) {
- a2 = shapeY[p+1]-shapeY[p];
- b2 = shapeX[p]-shapeX[p+1];
+ a2 = shapeLats[p+1]-shapeLats[p];
+ b2 = shapeLons[p]-shapeLons[p+1];
// compute determinant
d = a1*b2 - a2*b1;
if (d != 0) {
// lines are not parallel, check intersecting points
- c2 = a2*shapeX[p+1] + b2*shapeY[p+1];
+ c2 = a2*shapeLons[p+1] + b2*shapeLats[p+1];
s = (1/d)*(b2*c1 - b1*c2);
t = (1/d)*(a1*c2 - a2*c1);
x00 = StrictMath.min(bbox[b][0], bbox[b+1][0]) - GeoEncodingUtils.TOLERANCE;
x01 = StrictMath.max(bbox[b][0], bbox[b+1][0]) + GeoEncodingUtils.TOLERANCE;
y00 = StrictMath.min(bbox[b][1], bbox[b+1][1]) - GeoEncodingUtils.TOLERANCE;
y01 = StrictMath.max(bbox[b][1], bbox[b+1][1]) + GeoEncodingUtils.TOLERANCE;
- x10 = StrictMath.min(shapeX[p], shapeX[p+1]) - GeoEncodingUtils.TOLERANCE;
- x11 = StrictMath.max(shapeX[p], shapeX[p+1]) + GeoEncodingUtils.TOLERANCE;
- y10 = StrictMath.min(shapeY[p], shapeY[p+1]) - GeoEncodingUtils.TOLERANCE;
- y11 = StrictMath.max(shapeY[p], shapeY[p+1]) + GeoEncodingUtils.TOLERANCE;
+ x10 = StrictMath.min(shapeLons[p], shapeLons[p+1]) - GeoEncodingUtils.TOLERANCE;
+ x11 = StrictMath.max(shapeLons[p], shapeLons[p+1]) + GeoEncodingUtils.TOLERANCE;
+ y10 = StrictMath.min(shapeLats[p], shapeLats[p+1]) - GeoEncodingUtils.TOLERANCE;
+ y11 = StrictMath.max(shapeLats[p], shapeLats[p+1]) + GeoEncodingUtils.TOLERANCE;
// check whether the intersection point is touching one of the line segments
boolean touching = ((x00 == s && y00 == t) || (x01 == s && y01 == t))
|| ((x10 == s && y10 == t) || (x11 == s && y11 == t));
@@ -195,30 +191,35 @@ public class GeoRelationUtils {
return false;
}
- private static boolean lineCrossesRect(double aX1, double aY1, double aX2, double aY2,
- final double rMinX, final double rMinY, final double rMaxX, final double rMaxY) {
+ private static boolean lineCrossesRect(double aLat1, double aLon1,
+ double aLat2, double aLon2,
+ final double rMinLat, final double rMaxLat,
+ final double rMinLon, final double rMaxLon) {
// short-circuit: if one point inside rect, other outside
- if (pointInRectPrecise(aX1, aY1, rMinX, rMinY, rMaxX, rMaxY) ?
- !pointInRectPrecise(aX2, aY2, rMinX, rMinY, rMaxX, rMaxY) : pointInRectPrecise(aX2, aY2, rMinX, rMinY, rMaxX, rMaxY)) {
+ if (pointInRectPrecise(aLat1, aLon1, rMinLat, rMaxLat, rMinLon, rMaxLon)) {
+ if (pointInRectPrecise(aLat2, aLon2, rMinLat, rMaxLat, rMinLon, rMaxLon) == false) {
+ return true;
+ }
+ } else if (pointInRectPrecise(aLat2, aLon2, rMinLat, rMaxLat, rMinLon, rMaxLon)) {
return true;
}
- return lineCrossesLine(aX1, aY1, aX2, aY2, rMinX, rMinY, rMaxX, rMaxY)
- || lineCrossesLine(aX1, aY1, aX2, aY2, rMaxX, rMinY, rMinX, rMaxY);
+ return lineCrossesLine(aLat1, aLon1, aLat2, aLon2, rMinLat, rMinLon, rMaxLat, rMaxLon)
+ || lineCrossesLine(aLat1, aLon1, aLat2, aLon2, rMaxLat, rMinLon, rMinLat, rMaxLon);
}
- private static boolean lineCrossesLine(final double aX1, final double aY1, final double aX2, final double aY2,
- final double bX1, final double bY1, final double bX2, final double bY2) {
+ private static boolean lineCrossesLine(final double aLat1, final double aLon1, final double aLat2, final double aLon2,
+ final double bLat1, final double bLon1, final double bLat2, final double bLon2) {
// determine if three points are ccw (right-hand rule) by computing the determinate
- final double aX2X1d = aX2 - aX1;
- final double aY2Y1d = aY2 - aY1;
- final double bX2X1d = bX2 - bX1;
- final double bY2Y1d = bY2 - bY1;
+ final double aX2X1d = aLon2 - aLon1;
+ final double aY2Y1d = aLat2 - aLat1;
+ final double bX2X1d = bLon2 - bLon1;
+ final double bY2Y1d = bLat2 - bLat1;
- final double t1B = aX2X1d * (bY2 - aY1) - aY2Y1d * (bX2 - aX1);
- final double test1 = (aX2X1d * (bY1 - aY1) - aY2Y1d * (bX1 - aX1)) * t1B;
- final double t2B = bX2X1d * (aY2 - bY1) - bY2Y1d * (aX2 - bX1);
- final double test2 = (bX2X1d * (aY1 - bY1) - bY2Y1d * (aX1 - bX1)) * t2B;
+ final double t1B = aX2X1d * (bLat2 - aLat1) - aY2Y1d * (bLon2 - aLon1);
+ final double test1 = (aX2X1d * (bLat1 - aLat1) - aY2Y1d * (bLon1 - aLon1)) * t1B;
+ final double t2B = bX2X1d * (aLat2 - bLat1) - bY2Y1d * (aLon2 - bLon1);
+ final double test2 = (bX2X1d * (aLat1 - bLat1) - bY2Y1d * (aLon1 - bLon1)) * t2B;
if (test1 < 0 && test2 < 0) {
return true;
@@ -226,19 +227,19 @@ public class GeoRelationUtils {
if (test1 == 0 || test2 == 0) {
// vertically collinear
- if (aX1 == aX2 || bX1 == bX2) {
- final double minAy = Math.min(aY1, aY2);
- final double maxAy = Math.max(aY1, aY2);
- final double minBy = Math.min(bY1, bY2);
- final double maxBy = Math.max(bY1, bY2);
+ if (aLon1 == aLon2 || bLon1 == bLon2) {
+ final double minAy = Math.min(aLat1, aLat2);
+ final double maxAy = Math.max(aLat1, aLat2);
+ final double minBy = Math.min(bLat1, bLat2);
+ final double maxBy = Math.max(bLat1, bLat2);
return !(minBy >= maxAy || maxBy <= minAy);
}
// horizontally collinear
- final double minAx = Math.min(aX1, aX2);
- final double maxAx = Math.max(aX1, aX2);
- final double minBx = Math.min(bX1, bX2);
- final double maxBx = Math.max(bX1, bX2);
+ final double minAx = Math.min(aLon1, aLon2);
+ final double maxAx = Math.max(aLon1, aLon2);
+ final double minBx = Math.min(bLon1, bLon2);
+ final double maxBx = Math.max(bLon1, bLon2);
return !(minBx >= maxAx || maxBx <= minAx);
}
@@ -249,107 +250,113 @@ public class GeoRelationUtils {
* Computes whether a rectangle is within a polygon (shared boundaries not allowed) with more rigor than the
* {@link GeoRelationUtils#rectWithinPolyApprox} counterpart
*/
- public static boolean rectWithinPolyPrecise(final double rMinX, final double rMinY, final double rMaxX, final double rMaxY,
- final double[] shapeX, final double[] shapeY, final double sMinX,
- final double sMinY, final double sMaxX, final double sMaxY) {
+ public static boolean rectWithinPolyPrecise(final double rMinLat, final double rMaxLat, final double rMinLon, final double rMaxLon,
+ final double[] shapeLats, final double[] shapeLons, final double sMinLat,
+ final double sMaxLat, final double sMinLon, final double sMaxLon) {
// check if rectangle crosses poly (to handle concave/pacman polys), then check that all 4 corners
// are contained
- return !(rectCrossesPolyPrecise(rMinX, rMinY, rMaxX, rMaxY, shapeX, shapeY, sMinX, sMinY, sMaxX, sMaxY) ||
- !pointInPolygon(shapeX, shapeY, rMinY, rMinX) || !pointInPolygon(shapeX, shapeY, rMinY, rMaxX) ||
- !pointInPolygon(shapeX, shapeY, rMaxY, rMaxX) || !pointInPolygon(shapeX, shapeY, rMaxY, rMinX));
+ return !(rectCrossesPolyPrecise(rMinLat, rMaxLat, rMinLon, rMaxLon, shapeLats, shapeLons, sMinLat, sMaxLat, sMinLon, sMaxLon) ||
+ !pointInPolygon(shapeLats, shapeLons, rMinLat, rMinLon) || !pointInPolygon(shapeLats, shapeLons, rMinLat, rMaxLon) ||
+ !pointInPolygon(shapeLats, shapeLons, rMaxLat, rMaxLon) || !pointInPolygon(shapeLats, shapeLons, rMaxLat, rMinLon));
}
/**
* Computes whether a rectangle is within a given polygon (shared boundaries allowed)
*/
- public static boolean rectWithinPolyApprox(final double rMinX, final double rMinY, final double rMaxX, final double rMaxY,
- final double[] shapeX, final double[] shapeY, final double sMinX,
- final double sMinY, final double sMaxX, final double sMaxY) {
+ public static boolean rectWithinPolyApprox(final double rMinLat, final double rMaxLat, final double rMinLon, final double rMaxLon,
+ final double[] shapeLats, final double[] shapeLons, final double sMinLat,
+ final double sMaxLat, final double sMinLon, final double sMaxLon) {
// approximation: check if rectangle crosses poly (to handle concave/pacman polys), then check one of the corners
// are contained
// short-cut: if bounding boxes cross, rect is not within
- if (rectCrosses(rMinX, rMinY, rMaxX, rMaxY, sMinX, sMinY, sMaxX, sMaxY) == true) {
+ if (rectCrosses(rMinLat, rMaxLat, rMinLon, rMaxLon, sMinLat, sMaxLat, sMinLon, sMaxLon) == true) {
return false;
}
- return !(rectCrossesPolyApprox(rMinX, rMinY, rMaxX, rMaxY, shapeX, shapeY, sMinX, sMinY, sMaxX, sMaxY)
- || !pointInPolygon(shapeX, shapeY, rMinY, rMinX));
+ return !(rectCrossesPolyApprox(rMinLat, rMaxLat, rMinLon, rMaxLon, shapeLats, shapeLons, sMinLat, sMaxLat, sMinLon, sMaxLon)
+ || !pointInPolygon(shapeLats, shapeLons, rMinLat, rMinLon));
}
/////////////////////////
// Circle relations
/////////////////////////
- private static boolean rectAnyCornersInCircle(final double rMinX, final double rMinY, final double rMaxX,
- final double rMaxY, final double centerLon, final double centerLat,
+ private static boolean rectAnyCornersInCircle(final double rMinLat, final double rMaxLat, final double rMinLon,
+ final double rMaxLon, final double centerLat, final double centerLon,
final double radiusMeters, final boolean approx) {
if (approx == true) {
- return rectAnyCornersInCircleSloppy(rMinX, rMinY, rMaxX, rMaxY, centerLon, centerLat, radiusMeters);
+ return rectAnyCornersInCircleSloppy(rMinLat, rMaxLat, rMinLon, rMaxLon, centerLat, centerLon, radiusMeters);
}
- double w = Math.abs(rMaxX - rMinX);
+ double w = Math.abs(rMaxLon - rMinLon);
if (w <= 90.0) {
- return SloppyMath.haversinMeters(centerLat, centerLon, rMinY, rMinX) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMaxY, rMinX) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMaxY, rMaxX) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMinY, rMaxX) <= radiusMeters;
+ return SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, rMinLon) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMaxLat, rMinLon) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMaxLat, rMaxLon) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, rMaxLon) <= radiusMeters;
}
// partition
w /= 4;
- final double p1 = rMinX + w;
+ final double p1 = rMinLon + w;
final double p2 = p1 + w;
final double p3 = p2 + w;
- return SloppyMath.haversinMeters(centerLat, centerLon, rMinY, rMinX) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMaxY, rMinX) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMaxY, p1) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMinY, p1) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMinY, p2) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMaxY, p2) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMaxY, p3) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMinY, p3) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMaxY, rMaxX) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMinY, rMaxX) <= radiusMeters;
+ return SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, rMinLon) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMaxLat, rMinLon) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMaxLat, p1) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, p1) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, p2) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMaxLat, p2) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMaxLat, p3) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, p3) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMaxLat, rMaxLon) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, rMaxLon) <= radiusMeters;
}
- private static boolean rectAnyCornersInCircleSloppy(final double rMinX, final double rMinY, final double rMaxX, final double rMaxY,
- final double centerLon, final double centerLat, final double radiusMeters) {
- return SloppyMath.haversinMeters(centerLat, centerLon, rMinY, rMinX) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMaxY, rMinX) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMaxY, rMaxX) <= radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMinY, rMaxX) <= radiusMeters;
+ private static boolean rectAnyCornersInCircleSloppy(final double rMinLat, final double rMaxLat, final double rMinLon, final double rMaxLon,
+ final double centerLat, final double centerLon, final double radiusMeters) {
+ return SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, rMinLon) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMaxLat, rMinLon) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMaxLat, rMaxLon) <= radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, rMaxLon) <= radiusMeters;
}
/**
* Compute whether any of the 4 corners of the rectangle (defined by min/max X/Y) are outside the circle (defined
* by centerLon, centerLat, radiusMeters)
*
- * Note: exotic rectangles at the poles (e.g., those whose lon/lat distance ratios greatly deviate from 1) can not
+ * Note: exotic rectangles at the poles (e.g., those whose lat/lon distance ratios greatly deviate from 1) can not
* be determined by using distance alone. For this reason the approx flag may be set to false, in which case the
* space will be further divided to more accurately compute whether the rectangle crosses the circle
*/
- private static boolean rectAnyCornersOutsideCircle(final double rMinX, final double rMinY, final double rMaxX,
- final double rMaxY, final double centerLon, final double centerLat,
+ private static boolean rectAnyCornersOutsideCircle(final double rMinLat, final double rMaxLat, final double rMinLon,
+ final double rMaxLon, final double centerLat, final double centerLon,
final double radiusMeters, final boolean approx) {
if (approx == true) {
- return rectAnyCornersOutsideCircleSloppy(rMinX, rMinY, rMaxX, rMaxY, centerLon, centerLat, radiusMeters);
+ return rectAnyCornersOutsideCircleSloppy(rMinLat, rMaxLat, rMinLon, rMaxLon, centerLat, centerLon, radiusMeters);
}
// if span is less than 70 degrees we can approximate using distance alone
- if (Math.abs(rMaxX - rMinX) <= 70.0) {
- return SloppyMath.haversinMeters(centerLat, centerLon, rMinY, rMinX) > radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMaxY, rMinX) > radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMaxY, rMaxX) > radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMinY, rMaxX) > radiusMeters;
+ if (Math.abs(rMaxLon - rMinLon) <= 70.0) {
+ return SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, rMinLon) > radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMaxLat, rMinLon) > radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMaxLat, rMaxLon) > radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, rMaxLon) > radiusMeters;
}
- return rectCrossesOblateCircle(centerLon, centerLat, radiusMeters, rMinX, rMinY, rMaxX, rMaxY);
+ return rectCrossesOblateCircle(centerLat, centerLon,
+ radiusMeters,
+ rMinLat, rMaxLat,
+ rMinLon, rMaxLon);
}
/**
- * Compute whether the rectangle (defined by min/max Lon/Lat) crosses a potentially oblate circle
+ * Compute whether the rectangle (defined by min/max Lat/Lon) crosses a potentially oblate circle
*
* TODO benchmark for replacing existing rectCrossesCircle.
*/
- public static boolean rectCrossesOblateCircle(double centerLon, double centerLat, double radiusMeters, double rMinLon, double rMinLat, double rMaxLon, double rMaxLat) {
+ private static boolean rectCrossesOblateCircle(double centerLat, double centerLon,
+ double radiusMeters,
+ double rMinLat, double rMaxLat,
+ double rMinLon, double rMaxLon) {
double w = Math.abs(rMaxLon - rMinLon);
final int segs = (int)Math.ceil(w / 45.0);
w /= segs;
@@ -373,14 +380,14 @@ public class GeoRelationUtils {
// else we treat as an oblate circle by slicing the longitude space and checking the azimuthal range
// OPTIMIZATION: this is only executed for latitude values "closeTo" the poles (e.g., 88.0 > lat < -88.0)
if ( (rMaxLat > 88.0 || rMinLat < -88.0)
- && (pt = GeoProjectionUtils.pointFromLonLatBearingGreatCircle(p1, rMinLat,
- GeoProjectionUtils.bearingGreatCircle(p1, rMinLat, p1, rMaxLat), radiusMeters - d1, pt))[1] < rMinLat || pt[1] < rMaxLat
- || (pt = GeoProjectionUtils.pointFromLonLatBearingGreatCircle(maxLon, rMinLat,
- GeoProjectionUtils.bearingGreatCircle(maxLon, rMinLat, maxLon, rMaxLat), radiusMeters - d2, pt))[1] < rMinLat || pt[1] < rMaxLat
- || (pt = GeoProjectionUtils.pointFromLonLatBearingGreatCircle(maxLon, rMinLat,
- GeoProjectionUtils.bearingGreatCircle(maxLon, rMinLat, (midLon = p1 + 0.5*(maxLon - p1)), rMaxLat),
- radiusMeters - SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, midLon), pt))[1] < rMinLat
- || pt[1] < rMaxLat == false ) {
+ && (pt = GeoProjectionUtils.pointFromLonLatBearingGreatCircle(rMinLat, p1,
+ GeoProjectionUtils.bearingGreatCircle(rMinLat, p1, rMaxLat, p1), radiusMeters - d1, pt))[1] < rMinLat || pt[1] < rMaxLat
+ || (pt = GeoProjectionUtils.pointFromLonLatBearingGreatCircle(rMinLat, maxLon,
+ GeoProjectionUtils.bearingGreatCircle(rMinLat, maxLon, rMaxLat, maxLon), radiusMeters - d2, pt))[1] < rMinLat || pt[1] < rMaxLat
+ || (pt = GeoProjectionUtils.pointFromLonLatBearingGreatCircle(rMinLat, maxLon,
+ GeoProjectionUtils.bearingGreatCircle(rMinLat, maxLon, rMaxLat, (midLon = p1 + 0.5*(maxLon - p1))),
+ radiusMeters - SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, midLon), pt))[1] < rMinLat
+ || pt[1] < rMaxLat == false ) {
return true;
}
p1 += w;
@@ -388,81 +395,77 @@ public class GeoRelationUtils {
return false;
}
- private static boolean rectAnyCornersOutsideCircleSloppy(final double rMinX, final double rMinY, final double rMaxX, final double rMaxY,
- final double centerLon, final double centerLat, final double radiusMeters) {
- return SloppyMath.haversinMeters(centerLat, centerLon, rMinY, rMinX) > radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMaxY, rMinX) > radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMaxY, rMaxX) > radiusMeters
- || SloppyMath.haversinMeters(centerLat, centerLon, rMinY, rMaxX) > radiusMeters;
- }
-
- /**
- * Convenience method for computing whether a rectangle is within a circle using additional precision checks
- */
- public static boolean rectWithinCircle(final double rMinX, final double rMinY, final double rMaxX, final double rMaxY,
- final double centerLon, final double centerLat, final double radiusMeters) {
- return rectWithinCircle(rMinX, rMinY, rMaxX, rMaxY, centerLon, centerLat, radiusMeters, false);
+ private static boolean rectAnyCornersOutsideCircleSloppy(final double rMinLat, final double rMaxLat, final double rMinLon, final double rMaxLon,
+ final double centerLat, final double centerLon, final double radiusMeters) {
+ return SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, rMinLon) > radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMaxLat, rMinLon) > radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMaxLat, rMaxLon) > radiusMeters
+ || SloppyMath.haversinMeters(centerLat, centerLon, rMinLat, rMaxLon) > radiusMeters;
}
/**
* Computes whether a rectangle is within a circle. Note: approx == true will be faster but less precise and may
* fail on large rectangles
*/
- public static boolean rectWithinCircle(final double rMinX, final double rMinY, final double rMaxX, final double rMaxY,
- final double centerLon, final double centerLat, final double radiusMeters,
+ public static boolean rectWithinCircle(final double rMinLat, final double rMaxLat, final double rMinLon, final double rMaxLon,
+ final double centerLat, final double centerLon, final double radiusMeters,
final boolean approx) {
- return rectAnyCornersOutsideCircle(rMinX, rMinY, rMaxX, rMaxY, centerLon, centerLat, radiusMeters, approx) == false;
- }
-
- /**
- * Determine if a bbox (defined by minLon, minLat, maxLon, maxLat) contains the provided point (defined by lon, lat)
- * NOTE: this is basic method that does not handle dateline or pole crossing. Unwrapping must be done before
- * calling this method.
- */
- public static boolean rectCrossesCircle(final double rMinX, final double rMinY, final double rMaxX, final double rMaxY,
- final double centerLon, final double centerLat, final double radiusMeters) {
- return rectCrossesCircle(rMinX, rMinY, rMaxX, rMaxY, centerLon, centerLat, radiusMeters, false);
+ return rectAnyCornersOutsideCircle(rMinLat, rMaxLat, rMinLon, rMaxLon, centerLat, centerLon, radiusMeters, approx) == false;
}
/**
* Computes whether a rectangle crosses a circle. Note: approx == true will be faster but less precise and may
* fail on large rectangles
+ *
+ * <p>NOTE: this is basic method that does not handle dateline or pole crossing. Unwrapping must be done before
+ * calling this method.
*/
- public static boolean rectCrossesCircle(final double rMinX, final double rMinY, final double rMaxX, final double rMaxY,
- final double centerLon, final double centerLat, final double radiusMeters,
+ public static boolean rectCrossesCircle(final double rMinLat, final double rMaxLat, final double rMinLon, final double rMaxLon,
+ final double centerLat, final double centerLon, final double radiusMeters,
final boolean approx) {
if (approx == true) {
- return rectAnyCornersInCircle(rMinX, rMinY, rMaxX, rMaxY, centerLon, centerLat, radiusMeters, approx)
- || isClosestPointOnRectWithinRange(rMinX, rMinY, rMaxX, rMaxY, centerLon, centerLat, radiusMeters, approx);
+ if (rectAnyCornersInCircle(rMinLat, rMaxLat, rMinLon, rMaxLon, centerLat, centerLon, radiusMeters, approx)) {
+ return true;
+ }
+ } else {
+ if (rectAnyCornersInCircle(rMinLat, rMaxLat, rMinLon, rMaxLon, centerLat, centerLon, radiusMeters, approx) &&
+ rectAnyCornersOutsideCircle(rMinLat, rMaxLat, rMinLon, rMaxLon, centerLat, centerLon, radiusMeters, approx)) {
+ return true;
+ }
}
-
- return (rectAnyCornersInCircle(rMinX, rMinY, rMaxX, rMaxY, centerLon, centerLat, radiusMeters, approx) &&
- rectAnyCornersOutsideCircle(rMinX, rMinY, rMaxX, rMaxY, centerLon, centerLat, radiusMeters, approx))
- || isClosestPointOnRectWithinRange(rMinX, rMinY, rMaxX, rMaxY, centerLon, centerLat, radiusMeters, approx);
+ if (isClosestPointOnRectWithinRange(rMinLat, rMaxLat, rMinLon, rMaxLon, centerLat, centerLon, radiusMeters, approx)) {
+ return true;
+ }
+ return false;
}
- private static boolean isClosestPointOnRectWithinRange(final double rMinX, final double rMinY, final double rMaxX, final double rMaxY,
- final double centerLon, final double centerLat, final double radiusMeters,
+ private static boolean isClosestPointOnRectWithinRange(final double rMinLat, final double rMaxLat,
+ final double rMinLon, final double rMaxLon,
+ final double centerLat, final double centerLon,
+ final double radiusMeters,
final boolean approx) {
double[] closestPt = {0, 0};
- GeoDistanceUtils.closestPointOnBBox(rMinX, rMinY, rMaxX, rMaxY, centerLon, centerLat, closestPt);
- boolean haverShortCut = SloppyMath.haversinMeters(centerLat, centerLon, closestPt[1], closestPt[0]) <= radiusMeters;
+ GeoDistanceUtils.closestPointOnBBox(rMinLat, rMaxLat, rMinLon, rMaxLon, centerLat, centerLon, closestPt);
+ boolean haverShortCut = SloppyMath.haversinMeters(centerLat, centerLon, closestPt[0], closestPt[1]) <= radiusMeters;
if (approx == true || haverShortCut == true) {
return haverShortCut;
}
- double lon1 = rMinX;
- double lon2 = rMaxX;
- double lat1 = rMinY;
- double lat2 = rMaxY;
- if (closestPt[0] == rMinX || closestPt[0] == rMaxX) {
- lon1 = closestPt[0];
+ double lon1 = rMinLon;
+ double lon2 = rMaxLon;
+ double lat1 = rMinLat;
+ double lat2 = rMaxLat;
+ if (closestPt[1] == rMinLon || closestPt[1] == rMaxLon) {
+ lon1 = closestPt[1];
lon2 = lon1;
- } else if (closestPt[1] == rMinY || closestPt[1] == rMaxY) {
- lat1 = closestPt[1];
+ } else if (closestPt[0] == rMinLat || closestPt[0] == rMaxLat) {
+ lat1 = closestPt[0];
lat2 = lat1;
}
- return lineCrossesSphere(lon1, lat1, 0, lon2, lat2, 0, centerLon, centerLat, 0, radiusMeters);
+ return lineCrossesSphere(lat1, lon1, 0,
+ lat2, lon2, 0,
+ centerLat, centerLon, 0,
+ radiusMeters);
}
/**
@@ -480,17 +483,18 @@ public class GeoRelationUtils {
* @param radiusMeters search sphere radius (in meters)
* @return whether the provided line segment is a secant of the
*/
- private static boolean lineCrossesSphere(double lon1, double lat1, double alt1, double lon2,
- double lat2, double alt2, double centerLon, double centerLat,
- double centerAlt, double radiusMeters) {
+ private static boolean lineCrossesSphere(double lat1, double lon1, double alt1,
+ double lat2, double lon2, double alt2,
+ double centerLat, double centerLon, double centerAlt,
+ double radiusMeters) {
// convert to cartesian 3d (in meters)
- double[] ecf1 = GeoProjectionUtils.llaToECF(lon1, lat1, alt1, null);
- double[] ecf2 = GeoProjectionUtils.llaToECF(lon2, lat2, alt2, null);
- double[] cntr = GeoProjectionUtils.llaToECF(centerLon, centerLat, centerAlt, null);
+ double[] ecf1 = GeoProjectionUtils.llaToECF(lat1, lon1, alt1, null);
+ double[] ecf2 = GeoProjectionUtils.llaToECF(lat2, lon2, alt2, null);
+ double[] cntr = GeoProjectionUtils.llaToECF(centerLat, centerLon, centerAlt, null);
// convert radius from arc radius to cartesian radius
- double[] oneEighty = GeoProjectionUtils.pointFromLonLatBearingGreatCircle(centerLon, centerLat, 180.0d, radiusMeters, new double[3]);
- GeoProjectionUtils.llaToECF(oneEighty[0], oneEighty[1], 0, oneEighty);
+ double[] oneEighty = GeoProjectionUtils.pointFromLonLatBearingGreatCircle(centerLat, centerLon, 180.0d, radiusMeters, new double[3]);
+ GeoProjectionUtils.llaToECF(oneEighty[1], oneEighty[0], 0, oneEighty);
radiusMeters = GeoDistanceUtils.linearDistance(oneEighty, cntr);// Math.sqrt(oneEighty[0]*cntr[0] + oneEighty[1]*cntr[1] + oneEighty[2]*cntr[2]);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/09013e09/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoUtils.java
----------------------------------------------------------------------
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoUtils.java b/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoUtils.java
index 6d755ce..935da60 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoUtils.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoUtils.java
@@ -34,7 +34,6 @@ import static org.apache.lucene.spatial.util.GeoProjectionUtils.MAX_LAT_RADIANS;
import static org.apache.lucene.spatial.util.GeoProjectionUtils.MAX_LON_RADIANS;
import static org.apache.lucene.spatial.util.GeoProjectionUtils.MIN_LAT_RADIANS;
import static org.apache.lucene.spatial.util.GeoProjectionUtils.MIN_LON_RADIANS;
-import static org.apache.lucene.spatial.util.GeoProjectionUtils.pointFromLonLatBearingGreatCircle;
import static org.apache.lucene.spatial.util.GeoProjectionUtils.SEMIMAJOR_AXIS;
/**
@@ -93,42 +92,8 @@ public final class GeoUtils {
return (off <= 180 ? off : 360-off) - 90;
}
- /**
- * Converts a given circle (defined as a point/radius) to an approximated line-segment polygon
- *
- * @param lon longitudinal center of circle (in degrees)
- * @param lat latitudinal center of circle (in degrees)
- * @param radiusMeters distance radius of circle (in meters)
- * @return a list of lon/lat points representing the circle
- */
- @SuppressWarnings({"unchecked", "rawtypes"})
- public static ArrayList<double[]> circleToPoly(final double lon, final double lat, final double radiusMeters) {
- double angle;
- // a little under-sampling (to limit the number of polygonal points): using archimedes estimation of pi
- final int sides = 25;
- ArrayList<double[]> geometry = new ArrayList();
- double[] lons = new double[sides];
- double[] lats = new double[sides];
-
- double[] pt = new double[2];
- final int sidesLen = sides - 1;
- for (int i = 0; i < sidesLen; ++i) {
- angle = (i * 360 / sides);
- pt = pointFromLonLatBearingGreatCircle(lon, lat, angle, radiusMeters, pt);
- lons[i] = pt[0];
- lats[i] = pt[1];
- }
- // close the poly
- lons[sidesLen] = lons[0];
- lats[sidesLen] = lats[0];
- geometry.add(lons);
- geometry.add(lats);
-
- return geometry;
- }
-
/** Compute Bounding Box for a circle using WGS-84 parameters */
- public static GeoRect circleToBBox(final double centerLon, final double centerLat, final double radiusMeters) {
+ public static GeoRect circleToBBox(final double centerLat, final double centerLon, final double radiusMeters) {
final double radLat = TO_RADIANS * centerLat;
final double radLon = TO_RADIANS * centerLon;
double radDistance = radiusMeters / SEMIMAJOR_AXIS;
@@ -155,11 +120,11 @@ public final class GeoUtils {
maxLon = MAX_LON_RADIANS;
}
- return new GeoRect(TO_DEGREES * minLon, TO_DEGREES * maxLon, TO_DEGREES * minLat, TO_DEGREES * maxLat);
+ return new GeoRect(TO_DEGREES * minLat, TO_DEGREES * maxLat, TO_DEGREES * minLon, TO_DEGREES * maxLon);
}
/** Compute Bounding Box for a polygon using WGS-84 parameters */
- public static GeoRect polyToBBox(double[] polyLons, double[] polyLats) {
+ public static GeoRect polyToBBox(double[] polyLats, double[] polyLons) {
if (polyLons.length != polyLats.length) {
throw new IllegalArgumentException("polyLons and polyLats must be equal length");
}
@@ -182,14 +147,14 @@ public final class GeoUtils {
maxLat = max(polyLats[i], maxLat);
}
// expand bounding box by TOLERANCE factor to handle round-off error
- return new GeoRect(max(minLon - TOLERANCE, MIN_LON_INCL), min(maxLon + TOLERANCE, MAX_LON_INCL),
- max(minLat - TOLERANCE, MIN_LAT_INCL), min(maxLat + TOLERANCE, MAX_LAT_INCL));
+ return new GeoRect(max(minLat - TOLERANCE, MIN_LAT_INCL), min(maxLat + TOLERANCE, MAX_LAT_INCL),
+ max(minLon - TOLERANCE, MIN_LON_INCL), min(maxLon + TOLERANCE, MAX_LON_INCL));
}
-
// some sloppyish stuff, do we really need this to be done in a sloppy way?
// unless it is performance sensitive, we should try to remove.
static final double PIO2 = Math.PI / 2D;
+
/**
* Returns the trigonometric sine of an angle converted as a cos operation.
* <p>
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/09013e09/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestGeoPointQuery.java
----------------------------------------------------------------------
diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestGeoPointQuery.java b/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestGeoPointQuery.java
index 2fd64bd..fe922dc 100644
--- a/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestGeoPointQuery.java
+++ b/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestGeoPointQuery.java
@@ -16,6 +16,8 @@
*/
package org.apache.lucene.spatial.geopoint.search;
+import java.util.Arrays;
+
import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
@@ -26,14 +28,14 @@ import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
-import org.apache.lucene.store.Directory;
-import org.apache.lucene.spatial.util.GeoEncodingUtils;
-import org.apache.lucene.spatial.geopoint.document.GeoPointField;
import org.apache.lucene.spatial.geopoint.document.GeoPointField.TermEncoding;
+import org.apache.lucene.spatial.geopoint.document.GeoPointField;
import org.apache.lucene.spatial.util.BaseGeoPointTestCase;
+import org.apache.lucene.spatial.util.GeoEncodingUtils;
import org.apache.lucene.spatial.util.GeoRect;
import org.apache.lucene.spatial.util.GeoRelationUtils;
import org.apache.lucene.spatial.util.GeoUtils;
+import org.apache.lucene.store.Directory;
import org.apache.lucene.util.SloppyMath;
import org.apache.lucene.util.TestUtil;
import org.junit.AfterClass;
@@ -62,27 +64,27 @@ public class TestGeoPointQuery extends BaseGeoPointTestCase {
@Override
protected void addPointToDoc(String field, Document doc, double lat, double lon) {
- doc.add(new GeoPointField(field, lon, lat, fieldType));
+ doc.add(new GeoPointField(field, lat, lon, fieldType));
}
@Override
protected Query newRectQuery(String field, GeoRect rect) {
- return new GeoPointInBBoxQuery(field, termEncoding, rect.minLon, rect.minLat, rect.maxLon, rect.maxLat);
+ return new GeoPointInBBoxQuery(field, termEncoding, rect.minLat, rect.maxLat, rect.minLon, rect.maxLon);
}
@Override
protected Query newDistanceQuery(String field, double centerLat, double centerLon, double radiusMeters) {
- return new GeoPointDistanceQuery(field, termEncoding, centerLon, centerLat, radiusMeters);
+ return new GeoPointDistanceQuery(field, termEncoding, centerLat, centerLon, radiusMeters);
}
@Override
protected Query newDistanceRangeQuery(String field, double centerLat, double centerLon, double minRadiusMeters, double radiusMeters) {
- return new GeoPointDistanceRangeQuery(field, termEncoding, centerLon, centerLat, minRadiusMeters, radiusMeters);
+ return new GeoPointDistanceRangeQuery(field, termEncoding, centerLat, centerLon, minRadiusMeters, radiusMeters);
}
@Override
protected Query newPolygonQuery(String field, double[] lats, double[] lons) {
- return new GeoPointInPolygonQuery(field, termEncoding, lons, lats);
+ return new GeoPointInPolygonQuery(field, termEncoding, lats, lons);
}
@BeforeClass
@@ -98,22 +100,22 @@ public class TestGeoPointQuery extends BaseGeoPointTestCase {
// this is a simple systematic test
GeoPointField[] pts = new GeoPointField[] {
- new GeoPointField(FIELD_NAME, -96.774, 32.763420, fieldType),
- new GeoPointField(FIELD_NAME, -96.7759895324707, 32.7559529921407, fieldType),
- new GeoPointField(FIELD_NAME, -96.77701950073242, 32.77866942010977, fieldType),
- new GeoPointField(FIELD_NAME, -96.7706036567688, 32.7756745755423, fieldType),
- new GeoPointField(FIELD_NAME, -139.73458170890808, 27.703618681345585, fieldType),
- new GeoPointField(FIELD_NAME, -96.4538113027811, 32.94823588839368, fieldType),
- new GeoPointField(FIELD_NAME, -96.65084838867188, 33.06047141970814, fieldType),
- new GeoPointField(FIELD_NAME, -96.7772, 32.778650, fieldType),
- new GeoPointField(FIELD_NAME, -177.23537676036358, -88.56029371730983, fieldType),
- new GeoPointField(FIELD_NAME, -26.779373834241003, 33.541429799076354, fieldType),
- new GeoPointField(FIELD_NAME, -77.35379276106497, 26.774024500421728, fieldType),
- new GeoPointField(FIELD_NAME, -14.796283808944777, -90.0, fieldType),
- new GeoPointField(FIELD_NAME, -178.8538113027811, 32.94823588839368, fieldType),
- new GeoPointField(FIELD_NAME, 178.8538113027811, 32.94823588839368, fieldType),
- new GeoPointField(FIELD_NAME, -73.998776, 40.720611, fieldType),
- new GeoPointField(FIELD_NAME, -179.5, -44.5, fieldType)};
+ new GeoPointField(FIELD_NAME, 32.763420, -96.774, fieldType),
+ new GeoPointField(FIELD_NAME, 32.7559529921407, -96.7759895324707, fieldType),
+ new GeoPointField(FIELD_NAME, 32.77866942010977, -96.77701950073242, fieldType),
+ new GeoPointField(FIELD_NAME, 32.7756745755423, -96.7706036567688, fieldType),
+ new GeoPointField(FIELD_NAME, 27.703618681345585, -139.73458170890808, fieldType),
+ new GeoPointField(FIELD_NAME, 32.94823588839368, -96.4538113027811, fieldType),
+ new GeoPointField(FIELD_NAME, 33.06047141970814, -96.65084838867188, fieldType),
+ new GeoPointField(FIELD_NAME, 32.778650, -96.7772, fieldType),
+ new GeoPointField(FIELD_NAME, -88.56029371730983, -177.23537676036358, fieldType),
+ new GeoPointField(FIELD_NAME, 33.541429799076354, -26.779373834241003, fieldType),
+ new GeoPointField(FIELD_NAME, 26.774024500421728, -77.35379276106497, fieldType),
+ new GeoPointField(FIELD_NAME, -90.0, -14.796283808944777, fieldType),
+ new GeoPointField(FIELD_NAME, 32.94823588839368, -178.8538113027811, fieldType),
+ new GeoPointField(FIELD_NAME, 32.94823588839368, 178.8538113027811, fieldType),
+ new GeoPointField(FIELD_NAME, 40.720611, -73.998776, fieldType),
+ new GeoPointField(FIELD_NAME, -44.5, -179.5, fieldType)};
for (GeoPointField p : pts) {
Document doc = new Document();
@@ -161,18 +163,18 @@ public class TestGeoPointQuery extends BaseGeoPointTestCase {
return GeoPointField.NUMERIC_TYPE_NOT_STORED;
}
- private TopDocs bboxQuery(double minLon, double minLat, double maxLon, double maxLat, int limit) throws Exception {
- GeoPointInBBoxQuery q = new GeoPointInBBoxQuery(FIELD_NAME, termEncoding, minLon, minLat, maxLon, maxLat);
+ private TopDocs bboxQuery(double minLat, double maxLat, double minLon, double maxLon, int limit) throws Exception {
+ GeoPointInBBoxQuery q = new GeoPointInBBoxQuery(FIELD_NAME, termEncoding, minLat, maxLat, minLon, maxLon);
return searcher.search(q, limit);
}
- private TopDocs polygonQuery(double[] lon, double[] lat, int limit) throws Exception {
- GeoPointInPolygonQuery q = new GeoPointInPolygonQuery(FIELD_NAME, termEncoding, lon, lat);
+ private TopDocs polygonQuery(double[] polyLats, double[] polyLons, int limit) throws Exception {
+ GeoPointInPolygonQuery q = new GeoPointInPolygonQuery(FIELD_NAME, termEncoding, polyLats, polyLons);
return searcher.search(q, limit);
}
- private TopDocs geoDistanceQuery(double lon, double lat, double radius, int limit) throws Exception {
- GeoPointDistanceQuery q = new GeoPointDistanceQuery(FIELD_NAME, termEncoding, lon, lat, radius);
+ private TopDocs geoDistanceQuery(double lat, double lon, double radius, int limit) throws Exception {
+ GeoPointDistanceQuery q = new GeoPointDistanceQuery(FIELD_NAME, termEncoding, lat, lon, radius);
return searcher.search(q, limit);
}
@@ -187,11 +189,11 @@ public class TestGeoPointQuery extends BaseGeoPointTestCase {
}
if (rect.minLon < rect.maxLon) {
- return GeoRelationUtils.pointInRectPrecise(pointLon, pointLat, rect.minLon, rect.minLat, rect.maxLon, rect.maxLat);
+ return GeoRelationUtils.pointInRectPrecise(pointLat, pointLon, rect.minLat, rect.maxLat, rect.minLon, rect.maxLon);
} else {
// Rect crosses dateline:
- return GeoRelationUtils.pointInRectPrecise(pointLon, pointLat, -180.0, rect.minLat, rect.maxLon, rect.maxLat)
- || GeoRelationUtils.pointInRectPrecise(pointLon, pointLat, rect.minLon, rect.minLat, 180.0, rect.maxLat);
+ return GeoRelationUtils.pointInRectPrecise(pointLat, pointLon, rect.minLat, rect.maxLat, -180.0, rect.maxLon)
+ || GeoRelationUtils.pointInRectPrecise(pointLat, pointLon, rect.minLat, rect.maxLat, rect.minLon, 180.0);
}
}
@@ -222,10 +224,10 @@ public class TestGeoPointQuery extends BaseGeoPointTestCase {
private static boolean radiusQueryCanBeWrong(double centerLat, double centerLon, double ptLon, double ptLat,
final double radius) {
- final long hashedCntr = GeoEncodingUtils.mortonHash(centerLon, centerLat);
+ final long hashedCntr = GeoEncodingUtils.mortonHash(centerLat, centerLon);
centerLon = GeoEncodingUtils.mortonUnhashLon(hashedCntr);
centerLat = GeoEncodingUtils.mortonUnhashLat(hashedCntr);
- final long hashedPt = GeoEncodingUtils.mortonHash(ptLon, ptLat);
+ final long hashedPt = GeoEncodingUtils.mortonHash(ptLat, ptLon);
ptLon = GeoEncodingUtils.mortonUnhashLon(hashedPt);
ptLat = GeoEncodingUtils.mortonUnhashLat(hashedPt);
@@ -237,25 +239,27 @@ public class TestGeoPointQuery extends BaseGeoPointTestCase {
}
public void testRectCrossesCircle() throws Exception {
- assertTrue(GeoRelationUtils.rectCrossesCircle(-180, -90, 180, 0.0, 0.667, 0.0, 88000.0));
+ assertTrue(GeoRelationUtils.rectCrossesCircle(-90, 0.0, -180, 180, 0.0, 0.667, 88000.0, false));
}
- private TopDocs geoDistanceRangeQuery(double lon, double lat, double minRadius, double maxRadius, int limit)
+ private TopDocs geoDistanceRangeQuery(double lat, double lon, double minRadius, double maxRadius, int limit)
throws Exception {
- GeoPointDistanceRangeQuery q = new GeoPointDistanceRangeQuery(FIELD_NAME, termEncoding, lon, lat, minRadius, maxRadius);
+ GeoPointDistanceRangeQuery q = new GeoPointDistanceRangeQuery(FIELD_NAME, termEncoding, lat, lon, minRadius, maxRadius);
return searcher.search(q, limit);
}
public void testBBoxQuery() throws Exception {
- TopDocs td = bboxQuery(-96.7772, 32.778650, -96.77690000, 32.778950, 5);
+ TopDocs td = bboxQuery(32.778650, 32.778950, -96.7772, -96.77690000, 5);
assertEquals("GeoBoundingBoxQuery failed", 4, td.totalHits);
}
public void testPolyQuery() throws Exception {
- TopDocs td = polygonQuery(new double[]{-96.7682647, -96.8280029, -96.6288757, -96.4929199,
- -96.6041564, -96.7449188, -96.76826477, -96.7682647},
+ TopDocs td = polygonQuery(
new double[]{33.073130, 32.9942669, 32.938386, 33.0374494,
- 33.1369762, 33.1162747, 33.073130, 33.073130}, 5);
+ 33.1369762, 33.1162747, 33.073130, 33.073130},
+ new double[]{-96.7682647, -96.8280029, -96.6288757, -96.4929199,
+ -96.6041564, -96.7449188, -96.76826477, -96.7682647},
+ 5);
assertEquals("GeoPolygonQuery failed", 2, td.totalHits);
}
@@ -277,56 +281,57 @@ public class TestGeoPointQuery extends BaseGeoPointTestCase {
double yMax = 1;//5;
// test cell crossing poly
- assertTrue(GeoRelationUtils.rectCrossesPolyApprox(xMin, yMin, xMax, yMax, px, py, xMinA, yMinA, xMaxA, yMaxA));
- assertFalse(GeoRelationUtils.rectCrossesPolyApprox(-5, 0, 0.000001, 5, px, py, xMin, yMin, xMax, yMax));
- assertTrue(GeoRelationUtils.rectWithinPolyApprox(-5, 0, -2, 5, px, py, xMin, yMin, xMax, yMax));
+ assertTrue(GeoRelationUtils.rectCrossesPolyApprox(yMin, yMax, xMin, yMax, py, px, yMinA, yMaxA, xMinA, xMaxA));
+ assertFalse(GeoRelationUtils.rectCrossesPolyApprox(0, 5, -5, 0.000001, py, px, yMin, yMax, xMin, xMax));
+ assertTrue(GeoRelationUtils.rectWithinPolyApprox(0, 5, -5, -2, py, px, yMin, yMax, xMin, xMax));
}
public void testBBoxCrossDateline() throws Exception {
- TopDocs td = bboxQuery(179.0, -45.0, -179.0, -44.0, 20);
+ TopDocs td = bboxQuery(-45.0, -44.0, 179.0, -179.0, 20);
assertEquals("BBoxCrossDateline query failed", 2, td.totalHits);
}
public void testWholeMap() throws Exception {
- TopDocs td = bboxQuery(GeoUtils.MIN_LON_INCL, GeoUtils.MIN_LAT_INCL, GeoUtils.MAX_LON_INCL, GeoUtils.MAX_LAT_INCL, 20);
+ TopDocs td = bboxQuery(GeoUtils.MIN_LAT_INCL, GeoUtils.MAX_LAT_INCL, GeoUtils.MIN_LON_INCL, GeoUtils.MAX_LON_INCL, 20);
assertEquals("testWholeMap failed", 24, td.totalHits);
- td = polygonQuery(new double[] {GeoUtils.MIN_LON_INCL, GeoUtils.MIN_LON_INCL, GeoUtils.MAX_LON_INCL, GeoUtils.MAX_LON_INCL, GeoUtils.MIN_LON_INCL},
- new double[] {GeoUtils.MIN_LAT_INCL, GeoUtils.MAX_LAT_INCL, GeoUtils.MAX_LAT_INCL, GeoUtils.MIN_LAT_INCL, GeoUtils.MIN_LAT_INCL}, 20);
+ td = polygonQuery(new double[] {GeoUtils.MIN_LAT_INCL, GeoUtils.MAX_LAT_INCL, GeoUtils.MAX_LAT_INCL, GeoUtils.MIN_LAT_INCL, GeoUtils.MIN_LAT_INCL},
+ new double[] {GeoUtils.MIN_LON_INCL, GeoUtils.MIN_LON_INCL, GeoUtils.MAX_LON_INCL, GeoUtils.MAX_LON_INCL, GeoUtils.MIN_LON_INCL},
+ 20);
assertEquals("testWholeMap failed", 24, td.totalHits);
}
public void smallTest() throws Exception {
- TopDocs td = geoDistanceQuery(-73.998776, 40.720611, 1, 20);
+ TopDocs td = geoDistanceQuery(40.720611, -73.998776, 1, 20);
assertEquals("smallTest failed", 2, td.totalHits);
}
// GeoBoundingBox should not accept invalid lat/lon
public void testInvalidBBox() throws Exception {
expectThrows(Exception.class, () -> {
- bboxQuery(179.0, -92.0, 181.0, -91.0, 20);
+ bboxQuery(-92.0, -91.0, 179.0, 181.0, 20);
});
}
public void testGeoDistanceQuery() throws Exception {
- TopDocs td = geoDistanceQuery(-96.4538113027811, 32.94823588839368, 6000, 20);
+ TopDocs td = geoDistanceQuery(32.94823588839368, -96.4538113027811, 6000, 20);
assertEquals("GeoDistanceQuery failed", 2, td.totalHits);
}
/** see https://issues.apache.org/jira/browse/LUCENE-6905 */
public void testNonEmptyTermsEnum() throws Exception {
- TopDocs td = geoDistanceQuery(-177.23537676036358, -88.56029371730983, 7757.999232959935, 20);
+ TopDocs td = geoDistanceQuery(-88.56029371730983, -177.23537676036358, 7757.999232959935, 20);
assertEquals("GeoDistanceQuery failed", 2, td.totalHits);
}
public void testMultiValuedQuery() throws Exception {
- TopDocs td = bboxQuery(-96.4538113027811, 32.7559529921407, -96.7706036567688, 32.7756745755423, 20);
+ TopDocs td = bboxQuery(32.7559529921407, 32.7756745755423, -96.4538113027811, -96.7706036567688, 20);
// 3 single valued docs + 2 multi-valued docs
assertEquals("testMultiValuedQuery failed", 5, td.totalHits);
}
public void testTooBigRadius() throws Exception {
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
- geoDistanceQuery(0.0, 85.0, 4000000, 20);
+ geoDistanceQuery(85.0, 0.0, 4000000, 20);
});
assertTrue(expected.getMessage().contains("exceeds maxRadius"));
}
@@ -335,19 +340,19 @@ public class TestGeoPointQuery extends BaseGeoPointTestCase {
* Explicitly large
*/
public void testGeoDistanceQueryHuge() throws Exception {
- TopDocs td = geoDistanceQuery(-96.4538113027811, 32.94823588839368, 6000000, 20);
+ TopDocs td = geoDistanceQuery(32.94823588839368, -96.4538113027811, 6000000, 20);
assertEquals("GeoDistanceQuery failed", 16, td.totalHits);
}
public void testGeoDistanceQueryCrossDateline() throws Exception {
- TopDocs td = geoDistanceQuery(-179.9538113027811, 32.94823588839368, 120000, 20);
+ TopDocs td = geoDistanceQuery(32.94823588839368, -179.9538113027811, 120000, 20);
assertEquals("GeoDistanceQuery failed", 3, td.totalHits);
}
// GeoDistanceQuery should not accept invalid lat/lon as origin
public void testInvalidGeoDistanceQuery() throws Exception {
expectThrows(Exception.class, () -> {
- geoDistanceQuery(181.0, 92.0, 120000, 20);
+ geoDistanceQuery(92.0, 181.0, 120000, 20);
});
}
@@ -357,7 +362,7 @@ public class TestGeoPointQuery extends BaseGeoPointTestCase {
}
public void testMortonEncoding() throws Exception {
- long hash = GeoEncodingUtils.mortonHash(180, 90);
+ long hash = GeoEncodingUtils.mortonHash(90, 180);
assertEquals(180.0, GeoEncodingUtils.mortonUnhashLon(hash), 0);
assertEquals(90.0, GeoEncodingUtils.mortonUnhashLat(hash), 0);
}
@@ -369,7 +374,7 @@ public class TestGeoPointQuery extends BaseGeoPointTestCase {
double lat = randomLat(small);
double lon = randomLon(small);
- long enc = GeoEncodingUtils.mortonHash(lon, lat);
+ long enc = GeoEncodingUtils.mortonHash(lat, lon);
double latEnc = GeoEncodingUtils.mortonUnhashLat(enc);
double lonEnc = GeoEncodingUtils.mortonUnhashLon(enc);
@@ -385,11 +390,11 @@ public class TestGeoPointQuery extends BaseGeoPointTestCase {
double lat = randomLat(small);
double lon = randomLon(small);
- long enc = GeoEncodingUtils.mortonHash(lon, lat);
+ long enc = GeoEncodingUtils.mortonHash(lat, lon);
double latEnc = GeoEncodingUtils.mortonUnhashLat(enc);
double lonEnc = GeoEncodingUtils.mortonUnhashLon(enc);
- long enc2 = GeoEncodingUtils.mortonHash(lon, lat);
+ long enc2 = GeoEncodingUtils.mortonHash(lat, lon);
double latEnc2 = GeoEncodingUtils.mortonUnhashLat(enc2);
double lonEnc2 = GeoEncodingUtils.mortonUnhashLon(enc2);
assertEquals(latEnc, latEnc2, 0.0);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/09013e09/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java
----------------------------------------------------------------------
diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java b/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java
index e14ffbd..a4f70d9 100644
--- a/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java
+++ b/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java
@@ -466,7 +466,7 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
lon1 = x;
}
- return new GeoRect(lon0, lon1, lat0, lat1);
+ return new GeoRect(lat0, lat1, lon0, lon1);
}
protected void initIndexWriterConfig(String field, IndexWriterConfig iwc) {