Как сгенерировать случайную широту и долготу с помощью модуля Python 3 random? Я уже гуглил, читал документацию и не нашел способа сделать это.

0
Vlad 8 Июл 2021 в 11:37

3 ответа

Лучший ответ

Проблема при использовании равномерного распределения для и широты и долготы. заключается в том, что физически широта НЕ распределена равномерно.

Поэтому, если вы планируете использовать эти случайные точки для чего-то вроде вычисления статистического усреднения или моделирования физического Монте-Карло, результаты могут оказаться неверными.

И если вы построите графическое представление «однородных» случайных точек, то будет казаться, что они сгруппированы в полярных регионах.

2

2

Простой алгоритм:

2 2 2 2 2 2 2

Так что у этих векторов нет привилегированного направления. После нормализации до единичной длины они равномерно распределены на единичной сфере. Они решают нашу проблему с распределением широты.

Идея реализована в следующем коде Python:

import  math
import  random

def randlatlon1():
    pi = math.pi
    cf = 180.0 / pi  # radians to degrees Correction Factor

    # get a random Gaussian 3D vector:
    gx = random.gauss(0.0, 1.0)
    gy = random.gauss(0.0, 1.0)
    gz = random.gauss(0.0, 1.0)

    # normalize to an equidistributed (x,y,z) point on the unit sphere:
    norm2 = gx*gx + gy*gy + gz*gz
    norm1 = 1.0 / math.sqrt(norm2)
    x = gx * norm1
    y = gy * norm1
    z = gz * norm1

    radLat = math.asin(z)      # latitude  in radians
    radLon = math.atan2(y,x)   # longitude in radians

    return (round(cf*radLat, 5), round(cf*radLon, 5))

Проверка работоспособности:

Евклидова геометрия предоставляет формулу для вероятности сферической зоны, определяемой минимальной / максимальной широтой и долготой. Соответствующий код Python выглядит так:

def computeProbaG(minLat, maxLat, minLon, maxLon):
    pi  = math.pi
    rcf = pi / 180.0  # degrees to radians Correction Factor
    lonProba = (maxLon - minLon) / 360.0
    minLatR  = rcf * minLat
    maxLatR  = rcf * maxLat
    latProba = (1.0/2.0) * (math.sin(maxLatR) - math.sin(minLatR))
    return (lonProba * latProba)

И мы также можем вычислить приближение той же вероятности путем случайной выборки, используя случайные точки, предоставляемые функцией, такой как randlatlon1, и подсчет того, что процент из них попадает в выбранную зону:

def computeProbaR(randlatlon, ranCount, minLat, maxLat, minLon, maxLon):
    norm  = 1.0 / ranCount
    pairs = [randlatlon()  for i in range(ranCount)]
    acceptor = lambda p: ( (p[0] > minLat)  and  (p[0] < maxLat)     and
                           (p[1] > minLon)  and   (p[1] < maxLon) )
    selCount = sum(1 for p in filter(acceptor, pairs))
    return (norm * selCount)

Обладая этими двумя функциями, мы можем проверять различные наборы геометрических параметров. что геометрические и вероятностные результаты хорошо согласуются с ranCount, установленным на один миллион случайных точек:

ranCount = 1000*1000
print (" ")
probaG1 = computeProbaG(                       30, 60, 45, 90)
probaR1 = computeProbaR(randlatlon1, ranCount, 30, 60, 45, 90)
print ("probaG1 = %f" % probaG1)
print ("probaR1 = %f" % probaR1)
print (" ")
probaG2 = computeProbaG(                        10, 55, -40, 160)
probaR2 = computeProbaR(randlatlon1, ranCount,  10, 55, -40, 160)
print ("probaG2 = %f" % probaG2)
print ("probaR2 = %f" % probaR2)
print (" ")

Выполнение вывода:

$ python3 georandom.py

probaG1 = 0.022877
probaR1 = 0.022852
 
probaG2 = 0.179307
probaR2 = 0.179644

$

Таким образом, эти два вида чисел, похоже, здесь разумно согласуются.

1
jpmarinier 10 Июл 2021 в 16:03

Создайте случайное число между

Latitude: -85 to +85 (actually -85.05115 for some reason)

Longitude: -180 to +180

0
tandem 8 Июл 2021 в 08:41

Как написал @tandem в своем ответе, диапазон по широте почти -90 to +90 (он сокращен на картах), а по долготе - -180 to +180. Чтобы сгенерировать случайные числа с плавающей запятой в этом диапазоне, используйте функцию random.uniform:

import random

# returns (lat, lon)
def randlatlon():
    return (round(random.uniform( -90,  90), 5),
            round(random.uniform(-180, 180), 5))

Оно округляется до 5 цифр после запятой, поскольку в дополнительной точности нет необходимости.

0
Vlad 8 Июл 2021 в 09:15