在半径内随机生成latlng会产生一个超出范围的点

Koa*_*ied 2 java android

我正在尝试在半径内生成一个点,我得到的值不正确.有人介意看看我经常做错了什么?这是一个在不同问题上发布的公式化方法......

  public static Location generateLocationWithinRadius(Location myCurrentLocation) {
    return getLocationInLatLngRad(1000, myCurrentLocation);
}

protected static Location getLocationInLatLngRad(double radiusInMeters, Location currentLocation) {
    double x0 = currentLocation.getLatitude();
    double y0 = currentLocation.getLongitude();

    Random random = new Random();

    // Convert radius from meters to degrees
    double radiusInDegrees = radiusInMeters / 111000f;

    double u = random.nextDouble();
    double v = random.nextDouble();
    double w = radiusInDegrees * Math.sqrt(u);
    double t = 2 * Math.PI * v;
    double x = w * Math.cos(t);
    double y = w * Math.sin(t);

    double new_x = x / Math.cos(y0);
    double new_y = y / Math.cos(x0);
    double foundLatitude;
    double foundLongitude;
    boolean shouldAddOrSubtractLat = random.nextBoolean();
    boolean shouldAddOrSubtractLon = random.nextBoolean();
    if (shouldAddOrSubtractLat) {
        foundLatitude = new_x + x0;
    } else {
        foundLatitude = x0 - new_x;
    }
    if (shouldAddOrSubtractLon) {
        foundLongitude = new_y + y0;
    } else {
        foundLongitude = y0 - new_y;
    }
    Location copy = new Location(currentLocation);
    copy.setLatitude(foundLatitude);
    copy.setLongitude(foundLongitude);
    return copy;
}
Run Code Online (Sandbox Code Playgroud)

我还应该说,由于某种原因,有效点在查看时会产生统一的坐标线.

我认为纬度是正确处理而经度不是.

Mar*_*nen 11

您的代码似乎或多或少基于gis.stackexchange.com上提供的想法 , 并在此讨论本讨论中进行了更多讨论.

如果我们根据这些讨论仔细研究它,那么它可能更有意义.

为了容易地将值限制为圆形,它使用随机化方向和距离的方法.首先,我们得到0.0 ... 1.0之间的两个随机双精度值:

double u = random.nextDouble();
double v = random.nextDouble();
Run Code Online (Sandbox Code Playgroud)

由于半径以米为单位并且计算需要度数,因此将其转换为:

double radiusInDegrees = radiusInMeters / 111000f;
Run Code Online (Sandbox Code Playgroud)

这里使用赤道的度数与米的比率.(维基百科建议111320米.)

为了使随机点的分布更均匀,距离用平方根补偿:

w = r * sqrt(u)
Run Code Online (Sandbox Code Playgroud)

否则,中心附近与远离中心的点数量将存在统计偏差.1的平方根为0,当然为0,因此将随机双根的根乘以预期的最大值.radius始终给出介于0和半径之间的值.

然后另一个随机双倍乘以2*pi,因为整圆中有2*pi弧度:

t = 2 * Pi * v
Run Code Online (Sandbox Code Playgroud)

我们现在的角度介于0 ... 2*pi之间,即0 ... 360度.

然后使用随机距离和随机角度,使用基本三角函数计算随机x和y坐标增量:

x = w * cos(t) 
y = w * sin(t)
Run Code Online (Sandbox Code Playgroud)

[x,y]再分一些随机的距离w离朝方向的原始坐标t.

然后用三角学(y0中心的y坐标)补偿经度线之间的变化距离:

x' = x / cos(y0)
Run Code Online (Sandbox Code Playgroud)

y0如果cos()期望角度为弧度,则上面需要转换为弧度.在Java中它确实如此.

然后建议将这些增量值添加到原始坐标.该cossin为全圆的角度的一半是负的,因此只是将是罚款.一些随机点将从格林威治向西,从赤道向南.如果要进行加法或减法,则无需随机化.

所以随机点就是(x'+x0, y+y0).

我不知道为什么你的代码有:

double new_y = y / Math.cos(x0);
Run Code Online (Sandbox Code Playgroud)

就像说我们可以忽略shouldAddOrSubtractLatshouldAddOrSubtractLon.

在我看来,x指的是从左到右或从西到东的东西.即使经度线从南到北,经度值也会增长.所以让我们用x经度和y纬度.

那么剩下的是什么?就像是:

protected static Location getLocationInLatLngRad(double radiusInMeters, Location currentLocation) {
    double x0 = currentLocation.getLongitude();
    double y0 = currentLocation.getLatitude();

    Random random = new Random();

    // Convert radius from meters to degrees.
    double radiusInDegrees = radiusInMeters / 111320f;

    // Get a random distance and a random angle.
    double u = random.nextDouble();
    double v = random.nextDouble();
    double w = radiusInDegrees * Math.sqrt(u);
    double t = 2 * Math.PI * v;
    // Get the x and y delta values.
    double x = w * Math.cos(t);
    double y = w * Math.sin(t);

    // Compensate the x value.
    double new_x = x / Math.cos(Math.toRadians(y0));

    double foundLatitude;
    double foundLongitude;

    foundLatitude = y0 + y;
    foundLongitude = x0 + new_x;

    Location copy = new Location(currentLocation);
    copy.setLatitude(foundLatitude);
    copy.setLongitude(foundLongitude);
    return copy;
}
Run Code Online (Sandbox Code Playgroud)