Проверка того, является ли геокоординатная точка сушей или океаном, используя картографические данные и данные Natural Earth 10m

Ответ на предыдущий вопрос «Проверьте, является ли точка геокоординат суши или океана с помощью картографии» См. https://stackoverflow.com/questions/asktitle=Checking%20if%20a%20geocoordinate%20point%20is%20land%20or%20ocean%20using%20cartopy%20and%20Natural%20Earth%2010m%20data предложил использовать следующий код, чтобы определить, является ли геокоордината is_land:

    import cartopy.io.shapereader as shpreader
    import shapely.geometry as sgeom
    from shapely.ops import unary_union
    from shapely.prepared import prep

    land_shp_fname = shpreader.natural_earth(resolution='50m',
                                   category='physical', name='land')

    land_geom = 
    unary_union(list(shpreader.Reader(land_shp_fname).geometries()))
    land = prep(land_geom)

    def is_land(x, y):
       return land.contains(sgeom.Point(x, y))

Когда разрешение шейп-файла «физическая» «суша» Natural Earth изменяется на «10 м», этот код возвращает неожиданный результат «True» для геокоординаты (0,0).

    >>> print(is_land(0, 0))
    True

Это проблема с данными шейп-файла Natural Earth или красивым служебным кодом?

    print shapely.__version__
    1.6.4.post1

person B. Leas    schedule 06.08.2018    source источник
comment
Исправление: веб-сайт для предыдущего вопроса. Проверьте, является ли точка геокоординат суша или океан, используя картографию: stackoverflow.com/questions/47894513/   -  person B. Leas    schedule 06.08.2018


Ответы (2)


Любопытный. Я определенно видел случай, когда unary_union создает неверную геометрию. Запуск land_geom.is_valid в этом случае занимает значительное время, но на самом деле утверждает, что это допустимая геометрия. Если есть сомнения, общий трюк с GEOS / Shapely заключается в буферизации на 0, что часто приводит к улучшенной геометрии, представляющей геометрию, которая у нас была раньше, в улучшенной форме. Выполнение этого также претендует на получение действительной геометрии.

К сожалению, результат остается ... запрос продолжает сообщать, что есть земля в 0, 0 ...

В этот момент я немного растерялся. Если есть сомнения, всегда стоит взглянуть на данные. На предмет вменяемости я проверил с помощью Карты Google, чтобы подтвердить, что на 0, 0 определенно нет земли. Затем я взглянул на геометрию, которую мы создали с помощью следующего кода:

import cartopy.crs as ccrs
import matplotlib.pyplot as plt

ax = plt.subplot(1, 2, 1, projection=ccrs.PlateCarree())
ax.add_geometries([b], ccrs.PlateCarree(), facecolor='green', edgecolor='none')

ax = plt.subplot(1, 2, 2, projection=ccrs.PlateCarree())
ax.add_geometries([b], ccrs.PlateCarree(), facecolor='green', edgecolor='none')
box_size = 5e-2
ax.set_extent([-box_size, box_size, -box_size, box_size])
ax.xaxis.set_visible(True)
ax.yaxis.set_visible(True)

Есть ли земля на 0, 0?

Вот, кажется, есть идеально квадратный участок земли размером примерно 1 милю ^ 2, расположенный точно в 0, 0! Сторонники теории заговора обрадовались бы идее, что это может быть настоящий участок земли, вычищенный ведущими СМИ, используемый для военных исследований инопланетян, и дом Элвиса, но я подозреваю, что более приземленный ответ заключается в том, что в данных есть ошибка ( или возможно в инструментах, считывающих данные).

Затем я провел быстрое исследование с помощью fiona, чтобы узнать, загружает ли он также геометрию для данного область:

import fiona
c = fiona.open(land_shp_fname)
hits = list(c.items(bbox=(-0.01, -0.01, 0.01, 0.01)))
len(hits)
hits

Результат однозначный ... здесь действительно есть геометрия, и она даже меньше, чем предполагает график (возможно, из-за допуска буфера с плавающей запятой?):

[(9,
  {'type': 'Feature',
   'id': '9',
   'geometry': {'type': 'Polygon',
    'coordinates': [[(-0.004789435546374336, -0.004389928165484299),
      (-0.004789435546374336, 0.00481690381926197),
      (0.004328009720073429, 0.00481690381926197),
      (0.004328009720073429, -0.004389928165484299),
      (-0.004789435546374336, -0.004389928165484299)]]},
   'properties': OrderedDict([('featurecla', 'Null island'),
                ('scalerank', 100),
                ('min_zoom', 100.0)])})]

Быстрый поиск по названию этого места «Нулевой остров», к моему ужасу, показывает, что это намеренная ошибка данных ... https://en.wikipedia.org/wiki/Null_Island и https://blogs.loc.gov/maps/2016/04/the-geographic-oddity-of-null-island/ подробно Null Подъем острова из глубины (фактически около 5000 м).

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

Итак, возьмем свой код и немного подправим:

land_shp_fname = shpreader.natural_earth(
    resolution='10m', category='physical', name='land')

land_geom = unary_union(
    [record.geometry
     for record in shpreader.Reader(land_shp_fname).records()
     if record.attributes.get('featurecla') != "Null island"])

land = prep(land_geom)

def is_land(x, y):
   return land.contains(sgeom.Point(x, y))

В итоге мы получаем функцию, которая оценивает набор данных Natural Earth в масштабе 1: 10 000 000 (10 м), чтобы определить, является ли точка морем или сушей, без учета странности нулевого острова, которая поступает из набора данных Natural Earth.

>>> print(is_land(0, 0))
False
person pelson    schedule 30.08.2018

Нулевой остров был добавлен как страна для устранения неполадок.

http://www.naturalearthdata.com/blog/natural-earth-version-1-3-release-notes/

person Keet    schedule 25.05.2019