Проверьте, является ли точка Землей или Водой в Картах Google - PullRequest
98 голосов
/ 10 марта 2012

.. а потом гугл-карты "вод от воды делят"

Ну, не в библейском смысле, а ..

Я хотел бы знать, какие у меня есть варианты, чтобы проверить, является ли точка [Lat, Lon] землей или водой.

Google Maps, очевидно, имеет эти данные (водоемы синие) - но есть ли в API что-то, что я могу использовать для этого? А если нет - разве они не служат ему, потому что никогда не думали об этом? Или потому что это слишком сложно?

Я не нашел никакой информации по этому вопросу - за исключением некоторых подобных вопросов здесь (например, поиск типа местности или высоты - но это не совсем то, что мне нужно).

Есть ли отдельный слой для этого? Опция? Команда? Или я должен пойти сделать это вручную?

Единственный способ, которым я могу придумать, как подойти к этому (должен ли я сделать это вручную), это проверить каждую обслуживаемую плитку на предмет точной точки, а затем проверить значение RGB для этого оттенка карты Google. Это только по теории - потому что на практике - я понятия не имею, как этого добиться, первое препятствие, которое я не знаю, как я могу преобразовать местоположение пикселя на плитке в точку [LatLon], например

Готовое решение будет намного проще.

Обратите внимание, что мне не нужна ВСЕ вода в мире (например - мне нет дела до ручьев, небольших прудов, большинства рек или бассейна вашего соседа. Мне нужны точки, где человек может рисковать без помощи плавучее транспортное средство)

РЕДАКТИРОВАТЬ I

После прочтения комментариев: Метод возвышения не является надежным, слишком много мест ниже уровня моря (вы можете увидеть список самых «глубоких» 10 здесь http://geology.com/below-sea-level/) и слишком много не имеющих выхода к морю водоемов над уровнем моря ( озера). Метод обратной геолокации ненадежен, потому что он будет возвращать геополитическую единицу, такую ​​как город, или штат, или НОЛЬ много раз. Я уже изучал эти псевдо-решения, прежде чем задавать вопрос, но на самом деле никто из них не ответил на этот вопрос - эти методы в лучшем случае плохо "угадывают".

Ответы [ 18 ]

2 голосов
/ 02 июля 2013

См. Ответ, который я дал на аналогичный вопрос - он использует "HIT_TEST_TERRAIN" из API Земли для достижения этой функции.

Вот рабочий пример идеи, которую я собрал здесь: http://www.msa.mmu.ac.uk/~fraser/ge/coord/

2 голосов
/ 02 июля 2013

Вот еще один пример на чистом JavaScript: http://jsfiddle.net/eUwMf/

Как видите, ideia в основном такая же, как rebe100x, получая изображение из API статической карты Google и читая первый пиксель:

$("#xGps, #yGps").change(function() {
    var img = document.getElementById('mapImg');

    // Bypass the security issue : drawing a canvas from an external URL.
    img.crossOrigin='anonymous';

    var xGps = $("#xGps").val();
    var yGps = $("#yGps").val();

    var mapUrl = "http://maps.googleapis.com/maps/api/staticmap?center=" + xGps + "," + yGps +
        "&zoom=14&size=20x20&maptype=roadmap&sensor=false";

    // mapUrl += "&key=" + key;

    $(img).attr("src", mapUrl);

    var canvas = $('<canvas/>')[0];
    canvas.width = img.width;
    canvas.height = img.height;
    canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);

    var pixelData = canvas.getContext('2d').getImageData(1, 1, 1, 1).data;

    if (pixelData[0] == 164 &&
        pixelData[1] == 190 &&
        pixelData[2] == 220) {
        $("#result").html("Water");
    } else {
        $("#result").html("Not water");
    }
});
2 голосов
/ 02 июля 2013

Я бы порекомендовал прокатить свой здесь.Вы можете использовать такие инструменты, как GDAL для запроса содержимого под точкой в ​​шейп-файле.Вы можете получить шейп-файлы для географии США из многих источников, включая Бюро переписей США .

. Это можно сделать через двоичные файлы GDAL, исходный код C или через swig в Java, Python и других.

Карты переписи населения

Информация GDAL

Пример запроса точки в Python

2 голосов
/ 18 августа 2012

К сожалению, этот ответ не входит в API Карт Google, и указанный ресурс не является бесплатным, но есть веб-сервис, предоставляемый DynamicGeometry, который предоставляет операцию GetWaterOrLand, которая принимает пару широта / долгота ( вы можете см. демо здесь ).

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

Надеюсь, это чем-то поможет.

1 голос
/ 27 мая 2017

Если List<Address> адрес возвращает 0, вы можете принять это местоположение как океан или Природные ресурсы. Просто добавьте код ниже в Ваш ответ Метод ответа API Google Адресов.

Инициализировать список ниже, как упоминалось

List<Address> addresses = geocoder.getFromLocation(latLng.latitude, latLng.longitude, 1);

if (addresses.size()==0) { Toast.MakeText(getApplicationContext,"Ocean or Natural Resources selected",Toast.LENGTH_SHORT).show(); }else{ }

1 голос
/ 18 мая 2015

Вот простое решение

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


Яндекс Документация: https://api.yandex.com.tr/maps/doc/geocoder/desc/concepts/input_params.xml


Шаги для получения названия океана:

1.) Сначала используйте Google для обратного геокодирования координаты.

2.) Если Google возвращает нулевые результаты, вероятность того, что координата находится над океаном, составляет 99%. Теперь сделайте вторичный обратный запрос геокодирования с теми же координатами к яндексу. Яндекс вернет ответ JSON с точными координатами, в этом ответе будут две пары «ключ»: «значение» важности

["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["kind"]

and

["GeoObject"]["name"]

Проверьте добрый ключ, если он == "гидро", вы знаете, что находитесь над водоемом, и, поскольку Google вернул нулевые результаты, вероятность того, что этот водоем является океаном, составляет 99,99%. Имя океана будет указанным выше ключом «имя».

Вот пример того, как я использую эту стратегию, написанную на Ruby

if result.data["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["kind"] == "hydro"
     ocean = result.data["GeoObject"]["name"] 
end

Шаги для получения названия Внутреннего водного объекта:

Для этого примера предположим, что наша координата лежит где-то в озере:

1.) Сначала воспользуйтесь Google, чтобы изменить геокодирование координат.

2.) Google, скорее всего, вернет результат, который является известным адресом по умолчанию на соседней земле. В результате он предоставляет координаты адреса, который он возвратил, эта координата не будет соответствовать той, которую вы указали. Измерьте расстояние между введенной вами координатой и координатой, возвращенной с результатом, если оно существенно отличается (например, 100 ярдов), затем выполните дополнительный запрос резервного копирования с помощью Яндекса и проверьте, чтобы увидеть значение ключа «kind», если оно является «гидро», то вы знаете, координата лежит на воде. Поскольку Google возвратил результат, в отличие от приведенного выше примера, вероятность того, что это внутренний водоем, составляет 99,99%, теперь вы можете получить название. Если "kind" не == "hydro", используйте геокодированный объект Google.

["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["kind"]

and

["GeoObject"]["name"]

Вот тот же код, написанный на Ruby для получения inland_body_of_water

if result.data["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["kind"] == "hydro"
     inland_body_of_water = result.data["GeoObject"]["name"] 
end

Примечание о лицензировании. Насколько я знаю, Google не позволяет вам использовать их данные для отображения на любых других картах, кроме тех, которые предлагает Google. У Яндекса, однако, очень гибкое лицензирование, и вы можете использовать их данные для отображения на картах Google.

Кроме того, у Яндекса есть высокий лимит скорости 50 000 запросов / день бесплатно и без обязательного ключа API.

0 голосов
/ 29 января 2019

Как полный новичок в Python, я не мог заставить решение SylvainB работать со скриптом python, который проверяет, находятся ли координаты на земле.Однако мне удалось выяснить это, загрузив OSGeo4W (https://trac.osgeo.org/osgeo4w/), а затем установив все, что мне было нужно, pip, Ipython, и проверил наличие всех указанных импортов. Я сохранил следующий код в виде файла .py.

Код для проверки, есть ли координаты на суше

###make sure you check these are there and working separately before using the .py file 

import ogr
from IPython import embed
from osgeo import osr
import osgeo

import random
#####generate a 1000 random coordinates
ran1= [random.uniform(-180,180) for x in range(1,1001)]
ran2= [random.uniform(-180,180) for x in range(1,1001)]


drv = ogr.GetDriverByName('ESRI Shapefile') #We will load a shape file
ds_in = drv.Open("D:\Downloads\land-polygons-complete-4326\land-polygons-complete-4326\land_polygons.shp")    #Get the contents of the shape file
lyr_in = ds_in.GetLayer(0)    #Get the shape file's first layer

#Put the title of the field you are interested in here
idx_reg = lyr_in.GetLayerDefn().GetFieldIndex("P_Loc_Nm")

#If the latitude/longitude we're going to use is not in the projection
#of the shapefile, then we will get erroneous results.
#The following assumes that the latitude longitude is in WGS84
#This is identified by the number "4236", as in "EPSG:4326"
#We will create a transformation between this and the shapefile's
#project, whatever it may be
geo_ref = lyr_in.GetSpatialRef()
point_ref=osgeo.osr.SpatialReference()
point_ref.ImportFromEPSG(4326)
ctran=osgeo.osr.CoordinateTransformation(point_ref,geo_ref)
###check if the random coordinates are on land
def check(runs):
    lon=ran1[runs]
    lat=ran2[runs]
    #Transform incoming longitude/latitude to the shapefile's projection
    [lon,lat,z]=ctran.TransformPoint(lon,lat)
    #Create a point
    pt = ogr.Geometry(ogr.wkbPoint)
    pt.SetPoint_2D(0, lon, lat)
    #Set up a spatial filter such that the only features we see when we
    #loop through "lyr_in" are those which overlap the point defined above
    lyr_in.SetSpatialFilter(pt)
    #Loop through the overlapped features and display the field of interest
    for feat_in in lyr_in:
        return(lon, lat)

###give it a try
result = [check(x) for x in range(1,11)] ###checks first 10 coordinates

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

0 голосов
/ 04 июля 2013

У меня есть другое решение здесь. В текущей реализации карты Google она не рассчитывает направление / расстояние от местоположения воды до местоположения суши и наоборот. Почему мы не используем эту логику, чтобы определить, является ли точка землей или водой.

Например, давайте возьмем этот пример

если мы хотим определить, является ли точка x землей или водой, то

давайте проверим направление между точкой x и известной точкой y, которая является землей. Если он определяет направление / расстояние, то точка x - это земля, или же это вода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...