zoukankan      html  css  js  c++  java
  • Java 根据经纬度计算两点之间的距离

    package xxx.driver.business.utils;
    
    /**
     * <p>Represents a point on the surface of a sphere. (The Earth is almost
     * spherical.)</p>
     *
     * <p>To create an instance, call one of the static methods fromDegrees() or
     * fromRadians().</p>
     *
     * <p>This code was originally published at
     * <a href="http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates#Java">
     * http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates#Java</a>.</p>
     *
     * @author Jan Philip Matuschek
     * @version 22 September 2010
     */
    public class GeoLocation {
        private double radLat;  // latitude in radians
        private double radLon;  // longitude in radians
    
        private double degLat;  // latitude in degrees
        private double degLon;  // longitude in degrees
    
        private static final double EARTHS_RADIUS_KM = 6371.01;
        private static final double  EARTHS_RADIUS_M = 3958.762079;
    
        public static final int UNIT_KM = 0;
        public static final int UNIT_M = 1;
    
        private static final double MIN_LAT = Math.toRadians(-90d);  // -PI/2
        private static final double MAX_LAT = Math.toRadians(90d);   //  PI/2
        private static final double MIN_LON = Math.toRadians(-180d); // -PI
        private static final double MAX_LON = Math.toRadians(180d);  //  PI
    
        private GeoLocation () {
        }
    
        /**
         * @param latitude the latitude, in degrees.
         * @param longitude the longitude, in degrees.
         */
        public static GeoLocation fromDegrees(double latitude, double longitude) {
            GeoLocation result = new GeoLocation();
            result.radLat = Math.toRadians(latitude);
            result.radLon = Math.toRadians(longitude);
            result.degLat = latitude;
            result.degLon = longitude;
            result.checkBounds();
            return result;
        }
    
        /**
         *
         * @param unit 0 km || kilometers; 1 m || miles
         * @return
         */
        protected double getEarthsRadius(int unit) {
            return unit == UNIT_KM?EARTHS_RADIUS_KM:EARTHS_RADIUS_M;
        }
    
        /**
         * @param latitude the latitude, in radians.
         * @param longitude the longitude, in radians.
         */
        public static GeoLocation fromRadians(double latitude, double longitude) {
            GeoLocation result = new GeoLocation();
            result.radLat = latitude;
            result.radLon = longitude;
            result.degLat = Math.toDegrees(latitude);
            result.degLon = Math.toDegrees(longitude);
            result.checkBounds();
            return result;
        }
    
        private void checkBounds() {
            if (radLat < MIN_LAT || radLat > MAX_LAT ||
                    radLon < MIN_LON || radLon > MAX_LON)
                throw new IllegalArgumentException();
        }
    
        /**
         * @return the latitude, in degrees.
         */
        public double getLatitudeInDegrees() {
            return degLat;
        }
    
        /**
         * @return the longitude, in degrees.
         */
        public double getLongitudeInDegrees() {
            return degLon;
        }
    
        /**
         * @return the latitude, in radians.
         */
        public double getLatitudeInRadians() {
            return radLat;
        }
    
        /**
         * @return the longitude, in radians.
         */
        public double getLongitudeInRadians() {
            return radLon;
        }
    
        @Override
        public String toString() {
            return "(" + degLat + "u00B0, " + degLon + "u00B0) = (" +
                    radLat + " rad, " + radLon + " rad)";
        }
    
        /**
         * Computes the great circle distance between this GeoLocation instance
         * and the location argument.
         * @param radius the radius of the sphere, e.g. the average radius for a
         * spherical approximation of the figure of the Earth is approximately
         * 6371.01 kilometers.
         * @return the distance, measured in the same unit as the radius
         * argument.
         */
        public double distanceTo(GeoLocation location, double radius) {
            return Math.acos(Math.sin(radLat) * Math.sin(location.radLat) +
                    Math.cos(radLat) * Math.cos(location.radLat) *
                            Math.cos(radLon - location.radLon)) * radius;
        }
    
        /**
         *
         * @param location
         * @param unit
         * @return
         */
        public double distanceToByUnit(GeoLocation location, int unit) {
            return distanceTo(location, getEarthsRadius(unit));
        }
    
        /**
         * <p>Computes the bounding coordinates of all points on the surface
         * of a sphere that have a great circle distance to the point represented
         * by this GeoLocation instance that is less or equal to the distance
         * argument.</p>
         * <p>For more information about the formulae used in this method visit
         * <a href="http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates">
         * http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates</a>.</p>
         * @param distance the distance from the point represented by this
         * GeoLocation instance. Must me measured in the same unit as the radius
         * argument.
         * @param radius the radius of the sphere, e.g. the average radius for a
         * spherical approximation of the figure of the Earth is approximately
         * 6371.01 kilometers.
         * @return an array of two GeoLocation objects such that:<ul>
         * <li>The latitude of any point within the specified distance is greater
         * or equal to the latitude of the first array element and smaller or
         * equal to the latitude of the second array element.</li>
         * <li>If the longitude of the first array element is smaller or equal to
         * the longitude of the second element, then
         * the longitude of any point within the specified distance is greater
         * or equal to the longitude of the first array element and smaller or
         * equal to the longitude of the second array element.</li>
         * <li>If the longitude of the first array element is greater than the
         * longitude of the second element (this is the case if the 180th
         * meridian is within the distance), then
         * the longitude of any point within the specified distance is greater
         * or equal to the longitude of the first array element
         * <strong>or</strong> smaller or equal to the longitude of the second
         * array element.</li>
         * </ul>
         */
        public GeoLocation[] boundingCoordinates(double distance, double radius) {
    
            if (radius < 0d || distance < 0d)
                throw new IllegalArgumentException();
    
            // angular distance in radians on a great circle
            double radDist = distance / radius;
    
            double minLat = radLat - radDist;
            double maxLat = radLat + radDist;
    
            double minLon, maxLon;
            if (minLat > MIN_LAT && maxLat < MAX_LAT) {
                double deltaLon = Math.asin(Math.sin(radDist) /
                        Math.cos(radLat));
                minLon = radLon - deltaLon;
                if (minLon < MIN_LON) minLon += 2d * Math.PI;
                maxLon = radLon + deltaLon;
                if (maxLon > MAX_LON) maxLon -= 2d * Math.PI;
            } else {
                // a pole is within the distance
                minLat = Math.max(minLat, MIN_LAT);
                maxLat = Math.min(maxLat, MAX_LAT);
                minLon = MIN_LON;
                maxLon = MAX_LON;
            }
    
            return new GeoLocation[]{fromRadians(minLat, minLon),
                    fromRadians(maxLat, maxLon)};
        }
    }
  • 相关阅读:
    word2vec原理(一) CBOW与Skip-Gram模型基础
    条件随机场CRF(三) 模型学习与维特比算法解码
    条件随机场CRF(二) 前向后向算法评估标记序列概率
    linux下如何强制卸载设备?
    docker build时如何使用代理?
    如何配置docker使用代理?
    linux下tar解压时报"gzip: stdin: unexpected end of file"如何处理?
    ubuntu下如何安装valgrind?
    linux下如何睡眠1ms?
    linux用户空间如何控制gpio?
  • 原文地址:https://www.cnblogs.com/niejunlei/p/6202420.html
Copyright © 2011-2022 走看看