Я пытаюсь создать случайные места рядом с моим местоположением. Я хочу создать случайные пары широта / долгота внутри 200-метрового круга, окружающего мое местоположение.
Вот формула, которую я придумал (с помощью людей из StackOverFlow): (Случайное число от -1 до 1) * radius + (старая долгота) = новая долгота в радиусе старой долготы
(Случайное число от -1 до 1) * радиус + (старая широта) = новая широта в пределах радиуса старой широты
Дело в том, что с моей реализацией происходит что-то странное, потому что все случайные местоположения находятся слишком близко от моего центра местоположения, кажется, что формула не охватывает весь радиус.
Есть идеи, что может быть не так с моей формулой?
Отредактировано, чтобы показать текущую реализацию Java:
public static Location getLocation(Location location, int radius) {
Random random = new Random();
// Convert radius from meters to degrees
double radiusInDegrees = radius / METERS_IN_DEGREES;
double x0 = location.getLongitude() * 1E6;
double y0 = location.getLatitude() * 1E6;
double u = random.nextInt(1001) / 1000;
double v = random.nextInt(1001) / 1000;
double w = radiusInDegrees * Math.sqrt(u);
double t = 2 * Math.PI * v;
double x = w * Math.cos(t);
double y = w * Math.sin(t);
// Adjust the x-coordinate for the shrinking of the east-west distances
double new_x = x / Math.cos(y0);
// Set the adjusted location
Location newLocation = new Location("Loc in radius");
newLocation.setLongitude(new_x + x0);
newLocation.setLatitude(y + y0);
return newLocation;
}
Я не уверен, что я делаю неправильно, потому что новые места создаются посреди моря.
Есть идеи?
источник
random.nextInt(1001)/1000
вернет значение больше 1 примерно в 0,1% времени. Почему вы не используетеrandom.nextDouble
илиrandom.nextFloat
? (б) Умножениеx0
иy0
на1E6
весьма таинственное; не похоже, что это даст правильные результаты.Ответы:
Это сложно по двум причинам: во-первых, ограничение точек на круг вместо квадрата; во-вторых, учет искажений в расчетах расстояния.
Многие ГИС включают возможности, которые автоматически и прозрачно справляются с обоими сложностями. Однако теги здесь предполагают, что ГИС-независимое описание алгоритма может быть желательным.
Чтобы сгенерировать точки равномерно, случайно и независимо внутри круга радиуса r вокруг местоположения (x0, y0), начните с генерирования двух независимых равномерных случайных значений u и v в интервале [0, 1). (Это то, что почти каждый генератор случайных чисел предоставляет вам.) Вычислить
Желаемая случайная точка находится в местоположении (x + x0, y + y0).
При использовании географических ( широта, долгота ) координат тогда x0 (долгота) и y0 (широта) будут в градусах, но r , скорее всего, будет в метрах (или футах или милях или каком-либо другом линейном измерении). Сначала преобразуйте радиус r в градусы, как если бы вы находились рядом с экватором. Здесь около 111 300 метров в градусе.
Во-вторых, после генерации x и y, как в шаге (1), отрегулируйте x-координату для сокращения расстояний восток-запад:
Желаемая случайная точка находится в местоположении (x '+ x0, y + y0). Это приблизительная процедура. Для малых радиусов (менее нескольких сотен километров), которые не распространяются ни на один из полюсов Земли, обычно это будет настолько точно, что вы не сможете обнаружить какую-либо ошибку даже при генерации десятков тысяч случайных точек вокруг каждого центра (x0, y0) ,
источник
Реализовано для Javascript:
источник
Правильная реализация:
Я удалил зависимость от внешних библиотек, чтобы сделать ее более доступной.
источник
Принятый ответ и производные не работали для меня. Результаты были очень неточными.
Правильная реализация в javascript:
Полная суть здесь
В принятом ответе - я обнаружил, что точки распределены по эллипсу шириной в 1,5 раза больше его высоты (в Панаме) и в 8 раз выше его высоты (на севере Швеции). Если я удалил корректировку координаты х из ответа @ whuber, то эллипс искажается в другую сторону, в 8 раз больше его ширины.
Код в моем ответе был основан на алгоритмах отсюда
Ниже вы можете увидеть два jsfiddles, которые показывают проблему с растягивающимся эллипсом
Правильный алгоритм
Искаженный алгоритм
источник
whuberPointAtDistance()
:x1 = (w * Math.cos(t)) / Math.cos(y0 * (Math.PI / 180))
.В питоне
Выход
Расстояние между точками составляет 0,288044147914 Расстояние между точками составляет 0,409557451806 Расстояние между точками составляет 0,368260305716 Расстояние между точками составляет 0,340720560546 Расстояние между точками составляет 0,453773334731 Расстояние между точками составляет 0,460608754561 Расстояние между точками составляет 0,497188825576 Расстояние между точками составляет 0,603178188859 Расстояние между точками составляет 0,6288 Расстояние между точками составляет 0,703178188859 Расстояние между точками - 0.503691568896 Расстояние между точками - 0.175153349209 Расстояние между точками - 0.195149463735 Расстояние между точками - 0.424094009858 Расстояние между точками - 0.286807741494 Расстояние между точками - 0.558049206307 Расстояние между точками - 0.498612171417 Расстояние между точками - 0.047344718215 Расстояние между точками - 0.48428686
источник
Вы можете проверить результаты своих расчетов здесь . Прокрутите вниз до раздела «Пункт назначения с учетом расстояния и направления от начальной точки». Внизу есть даже простая формула JavaScript для реализации. Вам все еще нужно будет сгенерировать случайный азимут $ \ theta $ в радианах (измеренный по часовой стрелке с севера), хотя это должно быть довольно прямым. Эти формулы предполагают сферическую землю (хотя она эллипсоидальная), которая достаточно хороша, поскольку дает ошибки до 0,3%.
источник
Реализация для Swift
Получение lat и lng из геоэнкодера и передача его этой функции
В моем примере выше я получаю широту и долготу из гео-кодирования названия страны, так как каждый раз название страны дает одинаковую широту и долготу, что и в середине страны, поэтому мне нужна случайность.
источник
private void drawPolyline (double lat, double lng) {
источник