/** * 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.spatial.geometry; /** * Abstract base lat-lng class which can manipulate fixed point or floating * point based coordinates. Instances are immutable. * * @see FloatLatLng * * <p><font color="red"><b>NOTE:</b> This API is still in * flux and might change in incompatible ways in the next * release.</font> */ public abstract class LatLng { public abstract boolean isNormalized(); public abstract boolean isFixedPoint(); public abstract LatLng normalize(); public abstract int getFixedLat(); public abstract int getFixedLng(); public abstract double getLat(); public abstract double getLng(); public abstract LatLng copy(); public abstract FixedLatLng toFixed(); public abstract FloatLatLng toFloat(); /** * Convert the lat/lng into the cartesian coordinate plane such that all * world coordinates are represented in the first quadrant. * The x dimension corresponds to latitude and y corresponds to longitude. * The translation starts with the normalized latlng and adds 180 to the latitude and * 90 to the longitude (subject to fixed point scaling). */ public CartesianPoint toCartesian() { LatLng ll=normalize(); int lat=ll.getFixedLat(); int lng=ll.getFixedLng(); return new CartesianPoint( lng+180*FixedLatLng.SCALE_FACTOR_INT, lat+90*FixedLatLng.SCALE_FACTOR_INT ); } /** * The inverse of toCartesian(). Always returns a FixedLatLng. * @param pt */ public static LatLng fromCartesian(CartesianPoint pt) { int lat=pt.getY() - 90 * FixedLatLng.SCALE_FACTOR_INT; int lng=pt.getX() - 180 * FixedLatLng.SCALE_FACTOR_INT; return new FixedLatLng(lat, lng); } /** * Calculates the distance between two lat/lng's in miles. * Imported from mq java client. * * @param ll2 * Second lat,lng position to calculate distance to. * * @return Returns the distance in miles. */ public double arcDistance(LatLng ll2) { return arcDistance(ll2, DistanceUnits.MILES); } /** * Calculates the distance between two lat/lng's in miles or meters. * Imported from mq java client. Variable references changed to match. * * @param ll2 * Second lat,lng position to calculate distance to. * @param lUnits * Units to calculate distance, defaults to miles * * @return Returns the distance in meters or miles. */ public double arcDistance(LatLng ll2, DistanceUnits lUnits) { LatLng ll1 = normalize(); ll2 = ll2.normalize(); double lat1 = ll1.getLat(), lng1 = ll1.getLng(); double lat2 = ll2.getLat(), lng2 = ll2.getLng(); // Check for same position if (lat1 == lat2 && lng1 == lng2) return 0.0; // Get the m_dLongitude difference. Don't need to worry about // crossing 180 since cos(x) = cos(-x) double dLon = lng2 - lng1; double a = radians(90.0 - lat1); double c = radians(90.0 - lat2); double cosB = (Math.cos(a) * Math.cos(c)) + (Math.sin(a) * Math.sin(c) * Math.cos(radians(dLon))); double radius = (lUnits == DistanceUnits.MILES) ? 3963.205/* MILERADIUSOFEARTH */ : 6378.160187/* KMRADIUSOFEARTH */; // Find angle subtended (with some bounds checking) in radians and // multiply by earth radius to find the arc distance if (cosB < -1.0) return 3.14159265358979323846/* PI */* radius; else if (cosB >= 1.0) return 0; else return Math.acos(cosB) * radius; } private double radians(double a) { return a * 0.01745329251994; } @Override public String toString() { return "[" + getLat() + "," + getLng() + "]"; } /** * Calculate the midpoint between this point an another. Respects fixed vs floating point * @param other */ public abstract LatLng calculateMidpoint(LatLng other); @Override public abstract int hashCode(); @Override public abstract boolean equals(Object obj); }