Быстрая библиотека ГИС-библиотеки python, которая поддерживает большое окружение и многоугольник

Я искал географическую библиотеку для python. Мне нужно сделать следующее:

  1. Получите расстояние между 2 точками (в метрах) с использованием расстояния Великого круга (не расчет расстояния между линиями)
  2. Проверьте, находится ли точка внутри многоугольника
  3. Выполните 1 и 2 пару тысяч раз в секунду

В начале я просмотрел этот пост: модуль Python для хранения и запроса географических координат и начал использовать геофизику . Я столкнулся с двумя проблемами:

  1. Geopy не поддерживает многоугольники
  2. Высокое использование процессора geoPy (для вычисления расстояния между точкой и относительными 5000 точками требуется около 140 мс ЦП)

Я продолжал искать и находил лучшую библиотеку GIS для Python? и https://gis.stackexchange.com/ . Это выглядело многообещающим, поскольку geos использует выполненный код C, который должен быть более быстрым и стройным, поддерживает многоугольники. Проблема в том, что geos / OGR выполняет линейные вычисления расстояния вместо сферы. Это устраняет все другие модули, основанные на геосети (например, GEODjango и shapely). Я что-то упустил? Я не думаю, что я первый человек, который использует python для выполнения ГИС-вычислений и хочет получить точные результаты.

    2 Solutions collect form web for “Быстрая библиотека ГИС-библиотеки python, которая поддерживает большое окружение и многоугольник”

    ОБНОВИТЬ

    Перейдем теперь к завершению других 576 функций в этой библиотеке, не считая завершенных двух законченных многоугольных функций, трехмерных алгоритмов расстояния расстояния и двух новых – угла_бок_2д и angle_contains_ray_2d. Кроме того, я переключился на версию C, чтобы внешние элементы не нужны, упрощает работу. Поместите старую версию C ++ в каталог old_c ++, так что она все еще там.

    Протестированная производительность, она идентична приведенной в нижней части ответа.


    ОБНОВЛЕНИЕ 2

    Итак, просто быстрое обновление, я еще не закончил всю библиотеку (я всего лишь около 15% пути), но я добавил эти непроверенные функции, если они вам понадобятся сразу, на github, до добавьте в старую точку алгоритмы многоугольника и сферы.

    angle_box_2d angle_contains_ray_2d angle_deg_2d angle_half_2d # MLM: double * angle_rad_2d angle_rad_3d angle_rad_nd angle_turn_2d anglei_deg_2d anglei_rad_2d annulus_area_2d annulus_sector_area_2d annulus_sector_centroid_2d # MLM: double * ball_unit_sample_2d # MLM: double * ball_unit_sample_3d # MLM: double * ball_unit_sample_nd # MLM; double * basis_map_3d #double * box_01_contains_point_2d box_01_contains_point_nd box_contains_point_2d box_contains_point_nd box_ray_int_2d box_segment_clip_2d circle_arc_point_near_2d circle_area_2d circle_dia2imp_2d circle_exp_contains_point_2d circle_exp2imp_2d circle_imp_contains_point_2d circle_imp_line_par_int_2d circle_imp_point_dist_2d circle_imp_point_dist_signed_2d circle_imp_point_near_2d circle_imp_points_2d # MlM: double * circle_imp_points_3d # MLM: double * circle_imp_points_arc_2d circle_imp_print_2d circle_imp_print_3d circle_imp2exp_2d circle_llr2imp_2d # MLM: double * circle_lune_area_2d circle_lune_centroid_2d # MLM; double * circle_pppr2imp_3d 

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


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

    На github: https://github.com/hoonto/pygeometry

    Это всего лишь мост python для функций, описанных и реализованных здесь:

    http://people.sc.fsu.edu/~jburkardt/cpp_src/geometry/geometry.html

    Библиотека GEOMETRY довольно хороша на самом деле, поэтому я думаю, что будет полезно соединить все эти функции для python, что я, вероятно, буду сегодня вечером.

    Изменить: еще пару вещей

    1. Поскольку математические функции на самом деле скомпилированы C ++, вам, конечно же, необходимо убедиться, что общая библиотека находится на пути. Вы можете изменить файл geometry.py, указав там, где вы хотите поместить эту общую библиотеку.
    2. Только скомпилированные для linux, .o и .so были скомпилированы в x86_64 fedora.
    3. Алгоритмы сферического расстояния ожидают радианы, поэтому вам нужно преобразовать десятичные градусы lat / lon, например, в радианы, как показано в файле geometry.py.

    Если вам это нужно на Windows, дайте мне знать, это займет всего пару минут, чтобы это получилось в Visual Studio. Но если кто-то не спросит, я, вероятно, сейчас просто оставлю это в покое.

    Надеюсь это поможет!

    Rgds …. Hoonto / Matt

    (новая фиксация: SHA: 4fa2dbbe849c09252c7bd931edfe8db478de28e6 – исправлены некоторые вещи, такие как конверсии радиан, а также типы возврата для функций py. Также были добавлены некоторые базовые тесты производительности, чтобы убедиться, что библиотека работает соответственно.)

    Результаты тестов. На каждой итерации один вызов sphere_distance1 и один вызов polygon_contains_point_2d, поэтому 2 вызова в общую библиотеку.

    • ~ 0.062s: 2000 итераций, 4000 вызовов
    • ~ 0.603s: 20000 итераций, 40000 вызовов
    • ~ 0.905s: 30000 итераций, 60000 вызовов
    • ~ 1.198s: 40000 итераций, 80000 звонков

    Если сферического вычисления достаточно, я бы просто использовал numpy для расстояния и matplotlib для проверки полигона (поскольку вы найдете похожие предложения в stackoverflow).

     from math import asin, cos, radians, sin, sqrt import numpy as np def great_circle_distance_py(pnt1, pnt2, radius): """ Returns distance on sphere between points given as (latitude, longitude) in degrees. """ lat1 = radians(pnt1[0]) lat2 = radians(pnt2[0]) dLat = lat2 - lat1 dLon = radians(pnt2[1]) - radians(pnt1[1]) a = sin(dLat / 2.0) ** 2 + cos(lat1) * cos(lat2) * sin(dLon / 2.0) ** 2 return 2 * asin(min(1, sqrt(a))) * radius def great_circle_distance_numpy(pnt1, l_pnt2, radius): """ Similar to great_circle_distance_py(), but working on list of pnt2 and returning minimum. """ dLat = np.radians(l_pnt2[:, 0]) - radians(pnt1[0]) # slice latitude from list of (lat, lon) points dLon = np.radians(l_pnt2[:, 1]) - radians(pnt1[1]) a = np.square(np.sin(dLat / 2.0)) + np.cos(radians(pnt1[0])) * np.cos(np.radians(l_pnt2[:, 0])) * np.square(np.sin(dLon / 2.0)) return np.min(2 * np.arcsin(np.minimum(np.sqrt(a), len(a)))) * radius def aux_generateLatLon(): import random while 1: yield (90.0 - 180.0 * random.random(), 180.0 - 360.0 * random.random()) if __name__ == "__main__": ## 1. Great-circle distance earth_radius_m = 6371000.785 # sphere of same volume nPoints = 1000 nRep = 100 # just to measure time # generate a point and a list of to check against pnt1 = next(aux_generateLatLon()) l_pnt2 = np.array([next(aux_generateLatLon()) for i in range(nPoints)]) dMin1 = min([great_circle_distance_py(pnt1, pnt2, earth_radius_m) for pnt2 in l_pnt2]) dMin2 = great_circle_distance_numpy(pnt1, l_pnt2, earth_radius_m) # check performance import timeit print "random points: %7i" % nPoints print "repetitions : %7i" % nRep print "function 1 : %14.6fs" % (timeit.timeit('min([great_circle_distance_py(pnt1, pnt2, earth_radius_m) for pnt2 in l_pnt2])', 'from __main__ import great_circle_distance_py , pnt1, l_pnt2, earth_radius_m', number=nRep)) print "function 2 : %14.6fs" % (timeit.timeit('great_circle_distance_numpy(pnt1, l_pnt2, earth_radius_m)' , 'from __main__ import great_circle_distance_numpy, pnt1, l_pnt2, earth_radius_m', number=nRep)) # tell distance assert(abs(dMin1 - dMin2) < 0.0001) print print "min. distance: %14.6fm" % dMin1 ## 2. Inside polygon? # Note, not handled: # - the "pathological case" mentioned on http://paulbourke.net/geometry/polygonmesh/ # - special situations on a sphere: polygons covering "180 degrees longitude edge" or the Poles from matplotlib.path import Path x = y = 1.0 l_pnt2 = [(-x, -y), (x, -y), (x, y), (-x, y), (-x, -y)] path = Path(l_pnt2) print "isInside ?" for pnt in [(0.9, -1.9), (0.9, -0.9)]: print " ", pnt, bool(path.contains_point(pnt)) 

    Если вы хотите сделать больше, возможно, понадобится набор инструментов Quantum GIS: PyKGIS Developer Cookbook (docs.qgis.org) .

    Python - лучший язык программирования в мире.