Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何测量距离并基于两个纬度创建边界框+;Java中的经度点?_Java_Geocoding_Latitude Longitude - Fatal编程技术网

如何测量距离并基于两个纬度创建边界框+;Java中的经度点?

如何测量距离并基于两个纬度创建边界框+;Java中的经度点?,java,geocoding,latitude-longitude,Java,Geocoding,Latitude Longitude,我想找出两个不同点之间的距离。我知道这可以通过大圆距离来实现。 完成后,使用点和距离,我希望找到向北距离和向东距离的点,以便在点周围创建一个框。我们已经成功地使用它绘制了大量位置数据。有一个类具有一些基本功能,包括距离。下面是公式的Java实现。我在一个项目中使用它来计算lat/long之间的距离(以英里为单位) public static double distFrom(double lat1, double lng1, double lat2, double lng2) { dou

我想找出两个不同点之间的距离。我知道这可以通过大圆距离来实现。


完成后,使用点和距离,我希望找到向北距离和向东距离的点,以便在点周围创建一个框。

我们已经成功地使用它绘制了大量位置数据。有一个类具有一些基本功能,包括距离。

下面是公式的Java实现。我在一个项目中使用它来计算lat/long之间的距离(以英里为单位)

public static double distFrom(double lat1, double lng1, double lat2, double lng2) {
    double earthRadius = 3958.75; // miles (or 6371.0 kilometers)
    double dLat = Math.toRadians(lat2-lat1);
    double dLng = Math.toRadians(lng2-lng1);
    double sindLat = Math.sin(dLat / 2);
    double sindLng = Math.sin(dLng / 2);
    double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2)
            * Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2));
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    double dist = earthRadius * c;

    return dist;
    }
或者你可以用。据我所知,Apache2.0许可并用于一个生产系统:我的

短篇故事:

我正在寻找一个简单的地理图书馆,但找不到一个适合我需要的。谁愿意在每个应用程序中一遍又一遍地编写、测试和调试这些小地理工具呢?一定有更好的办法

因此,SimpleLatings作为一种存储经纬度数据、进行距离计算和创建形状边界的方法诞生了

我知道我已经晚了两年,无法帮助原创海报,但我的目标是帮助像我这样的人在搜索中找到这个问题。我很想让一些人使用它,并为这个小型轻量级实用程序的测试和设想做出贡献。

您可以使用,它使用考虑地球表面曲率的

实施过程如下:

import org.gavaghan.geodesy.*;
...
GeodeticCalculator geoCalc = new GeodeticCalculator();
Ellipsoid reference = Ellipsoid.WGS84;
GlobalPosition pointA = new GlobalPosition(latitude, longitude, 0.0);
GlobalPosition userPos = new GlobalPosition(userLat, userLon, 0.0);
double distance = geoCalc.calculateGeodeticCurve(reference, userPos, pointA).getEllipsoidalDistance();

产生的距离以米为单位。

要获得更精确的距离(0.5mm),还可以使用Vincenty近似值:

/**
 * Calculates geodetic distance between two points specified by latitude/longitude using Vincenty inverse formula
 * for ellipsoids
 * 
 * @param lat1
 *            first point latitude in decimal degrees
 * @param lon1
 *            first point longitude in decimal degrees
 * @param lat2
 *            second point latitude in decimal degrees
 * @param lon2
 *            second point longitude in decimal degrees
 * @returns distance in meters between points with 5.10<sup>-4</sup> precision
 * @see <a href="http://www.movable-type.co.uk/scripts/latlong-vincenty.html">Originally posted here</a>
 */
public static double distVincenty(double lat1, double lon1, double lat2, double lon2) {
    double a = 6378137, b = 6356752.314245, f = 1 / 298.257223563; // WGS-84 ellipsoid params
    double L = Math.toRadians(lon2 - lon1);
    double U1 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat1)));
    double U2 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat2)));
    double sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
    double sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);

    double sinLambda, cosLambda, sinSigma, cosSigma, sigma, sinAlpha, cosSqAlpha, cos2SigmaM;
    double lambda = L, lambdaP, iterLimit = 100;
    do {
        sinLambda = Math.sin(lambda);
        cosLambda = Math.cos(lambda);
        sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda)
                + (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
        if (sinSigma == 0)
            return 0; // co-incident points
        cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
        sigma = Math.atan2(sinSigma, cosSigma);
        sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
        cosSqAlpha = 1 - sinAlpha * sinAlpha;
        cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
        if (Double.isNaN(cos2SigmaM))
            cos2SigmaM = 0; // equatorial line: cosSqAlpha=0 (§6)
        double C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
        lambdaP = lambda;
        lambda = L + (1 - C) * f * sinAlpha
                * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
    } while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0);

    if (iterLimit == 0)
        return Double.NaN; // formula failed to converge

    double uSq = cosSqAlpha * (a * a - b * b) / (b * b);
    double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
    double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
    double deltaSigma = B
            * sinSigma
            * (cos2SigmaM + B
                    / 4
                    * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) - B / 6 * cos2SigmaM
                            * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
    double dist = b * A * (sigma - deltaSigma);

    return dist;
}
/**
*使用Vincenty逆公式计算由纬度/经度指定的两点之间的大地测量距离
*椭球
* 
*@param-lat1
*第一点纬度(十进制度数)
*@param lon1
*第一点经度(十进制度数)
*@param-lat2
*第二点纬度(十进制度数)
*@param lon2
*以十进制度数表示的第二点经度
*@返回精度为5.10-4的点之间的距离(以米为单位)
*@见
*/
公共静态双距离(双lat1、双lon1、双lat2、双lon2){
双a=6378137,b=6356752.314245,f=1/298.257223563;//WGS-84椭球面参数
双L=数学托拉迪安(lon2-lon1);
double U1=数学atan((1-f)*数学tan(数学toRadians(lat1));
double U2=Math.atan((1-f)*Math.tan(Math.toRadians(lat2));
double sinU1=Math.sin(U1),cosU1=Math.cos(U1);
双sinU2=Math.sin(U2),cosU2=Math.cos(U2);
双sinLambda、cosLambda、sinSigma、cosigma、sigma、sinAlpha、cosSqAlpha、cos2SigmaM;
双λ=L,λ=100;
做{
sinLambda=Math.sin(lambda);
cosLambda=Math.cos(lambda);
sinSigma=Math.sqrt((cosU2*sinLambda)*(cosU2*sinLambda)
+(cosU1*sinU2-sinU1*cosU2*cosLambda)*(cosU1*sinU2-sinU1*cosU2*cosLambda));
如果(sinSigma==0)
返回0;//共事件点
cosigma=sinU1*sinU2+cosU1*cosU2*cosLambda;
西格玛=数学atan2(sinSigma,cosigma);
sinAlpha=cosU1*cosU2*sinLambda/sinSigma;
cosSqAlpha=1-sinAlpha*sinAlpha;
cos2Sigam=cosSigma-2*sinU1*sinU2/cosSqAlpha;
if(双isNaN(cos2SigmaM))
Cos2Sigam=0;//赤道线:cosSqAlpha=0(§6)
双C=f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
lambdaP=lambda;
λ=L+(1-C)*f*sinAlpha
*(sigma+C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM));
}而(数学abs(lambda-lambdaP)>1e-12&--iterLimit>0);
if(iterLimit==0)
return Double.NaN;//公式收敛失败
双uSq=cosSqAlpha*(a*a-b*b)/(b*b);
双A=1+uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq));
双B=uSq/1024*(256+uSq*(-128+uSq*(74-47*uSq));
双deltaSigma=B
*辛西格玛
*(cos2SigmaM+B)
/ 4
*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-B/6*cos2SigmaM
*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM));
双区=b*A*(西格玛-德尔塔西格玛);
返回距离;
}

此代码自由改编自

修正的哈弗森距离公式

public static double HaverSineDistance(double lat1, double lng1, double lat2, double lng2) 
{
    // mHager 08-12-2012
    // http://en.wikipedia.org/wiki/Haversine_formula
    // Implementation

    // convert to radians
    lat1 = Math.toRadians(lat1);
    lng1 = Math.toRadians(lng1);
    lat2 = Math.toRadians(lat2);
    lng2 = Math.toRadians(lng2);

    double dlon = lng2 - lng1;
    double dlat = lat2 - lat1;

    double a = Math.pow((Math.sin(dlat/2)),2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(dlon/2),2);

    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

    return EARTH_RADIUS * c;
}   

我通常使用MATLAB和,然后使用Java中的代码使用它使我的生活简单得多。鉴于大多数学校都有免费的学生使用,你可以试用它(或获得试用版以忘掉你的工作)。


我知道有很多答案,但在做一些关于这个主题的研究时,我发现这里的大多数答案都使用哈弗森公式,但文森特公式实际上更准确。有一篇文章根据Javascript版本修改了计算,但它非常笨拙。我发现了一个更好的版本,因为:

  • 它也有一个开放的许可证
  • 它使用OOP原则
  • 它具有更大的灵活性来选择要使用的椭球体
  • 它有更多的方法来允许将来进行不同的计算
  • 这是有据可查的

  • 此方法将帮助您查找到地理位置之间的距离,单位为km

    private double getDist(double lat1, double lon1, double lat2, double lon2)
    {
        int R = 6373; // radius of the earth in kilometres
        double lat1rad = Math.toRadians(lat1);
        double lat2rad = Math.toRadians(lat2);
        double deltaLat = Math.toRadians(lat2-lat1);
        double deltaLon = Math.toRadians(lon2-lon1);
    
        double a = Math.sin(deltaLat/2) * Math.sin(deltaLat/2) +
                Math.cos(lat1rad) * Math.cos(lat2rad) *
                Math.sin(deltaLon/2) * Math.sin(deltaLon/2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    
        double d = R * c;
        return d;
    }
    

    对于Android,有一个简单的方法

     public static float getDistanceInMeter(LatLng start, LatLng end) { 
        float[] results = new float[1];
        Location.distanceBetween(start.latitude, start.longitude, end.latitude, end.longitude, results);
        return results[0];
    
    }
    
    )


    Kotlin版哈弗森配方奶粉。以米为单位返回结果。测试


    请注意,它将以英里为单位返回距离(因为earthRadius设置)。对于其他单位,请更改地球半径(有关更多信息,请参阅),是否有理由使用浮动而不是双精度?如果我理解正确,您可以通过简单地更改输入参数类型来提高结果的准确性
     public static float getDistanceInMeter(LatLng start, LatLng end) { 
        float[] results = new float[1];
        Location.distanceBetween(start.latitude, start.longitude, end.latitude, end.longitude, results);
        return results[0];
    
    }
    
    const val EARTH_RADIUS_IN_METERS = 6371007.177356707
    
    fun distance(lat1: Double, lng1: Double, lat2: Double, lng2: Double): Double {
        val latDiff = Math.toRadians(abs(lat2 - lat1))
        val lngDiff = Math.toRadians(abs(lng2 - lng1))
        val a = sin(latDiff / 2) * sin(latDiff / 2) +
            cos(Math.toRadians(lat1)) * cos(Math.toRadians(lat2)) *
            sin(lngDiff / 2) * sin(lngDiff / 2)
        val c = 2 * atan2(sqrt(a), sqrt(1 - a))
        return EARTH_RADIUS_IN_METERS * c
    }