Проверьте, является ли точка "Земля или вода" на Картах Google.

.. а затем Google-карты "разделяют воды из вод"

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

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

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

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

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

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

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

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

EDIT я ​​

После чтения комментариев: Метод повышения не является надежным, слишком много мест НИЖЕ уровня моря (вы можете увидеть список "самых глубоких" 10 здесь http://geology.com/below-sea-level/) и слишком много не имеющих выхода к морю водоемов ВЫШЕ уровень моря (озера). Метод обратной геолокации не является надежным, поскольку он будет возвращать геополитическую сущность, например город или штат, или ZERO много раз. Я уже рассматривал эти псевдорешения, прежде чем задавать вопрос, но никто из них не ответил на вопрос - эти методы плохо подходят в лучшем случае.

Ответ 1

Это два разных способа, вы можете попробовать:

  • Вы можете использовать Google Reverse Geocoding. В наборе результатов вы можете определить, является ли это водой, проверив types. В случае воды тип natural_feature. См. Больше на этой ссылке http://code.google.com/apis/maps/documentation/geocoding/#Types.

    Также вам нужно проверить имена функций, если они содержат Sea, Lake, Ocean и некоторые другие слова, связанные с водой для большей точности. Например, пустыни также natural_feature s.

    Prons. Все процессы обнаружения будут выполняться на клиентской машине. Нет необходимости создавать собственную серверную службу.

    Против - Очень неточно, и шансы, что вы получите "нет" в водах, очень высоки.

  • Вы можете определить воды/земли по пикселям, используя Google Статические карты. Но для этого вам нужно создать http-сервис.

    Это шаги, которые должна выполнить ваша служба:

    • Получите latitude, longitude и current zoom от клиента.
    • Отправить http://maps.googleapis.com/maps/api/staticmap?center={ широта , долгота }&zoom={ текущий zoom`} & size = 1x1 & maptype = roadmap & sensor = false запрос к службе Google Static Map.
    • Определить цвет пикселя статического изображения 1x1.
    • Ответьте на информацию об обнаружении.

    Вы не можете определить цвет пикселя на стороне клиента. Да, вы можете загружать статическое изображение на клиентскую машину и рисовать изображение на элементе canvas. Но вы не можете использовать getImageData контекста canvas для получения цвета пикселя. Это ограничивается политикой перекрестных доменов.

    Prons - высокоточное обнаружение

    Против - использование собственных ресурсов сервера для обнаружения

Ответ 2

Это не представляется возможным в любой текущей службе Google.

Но есть и другие сервисы, такие как Заказывать векторный JSON-сервис! Вы просто запрашиваете данные в URL-адресе, а получаете ответ JSON/XML.

Пример запроса: http://api.koordinates.com/api/vectorQuery.json?key=YOUR_GEODATA_KEY&layer=1298&x=-159.9609375&y=13.239945499286312&max_results=3&radius=10000&geometry=true&with_field_names=true

Вам необходимо зарегистрировать и указать свой номер и номер выбранного слоя. Вы можете найти все доступные репозиторий доступных слоев. Большинство слоев являются только региональными, но вы также можете найти глобальные, например World Coastline:

enter image description here

Когда вы выбираете слой, вы щелкаете по вкладке "Сервисы", вы получаете URL-адрес запроса примера. Я считаю, вам просто нужно зарегистрироваться и что это!

И теперь самое лучшее:

Вы можете загрузить свой слой!

Он не доступен сразу, ему нужно как-то его обработать, но он должен работать! Репозиторий уровня фактически выглядит так, как люди загружали их по мере необходимости.

Ответ 3

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

function isItWatter($lat,$lng) {

    $GMAPStaticUrl = "https://maps.googleapis.com/maps/api/staticmap?center=".$lat.",".$lng."&size=40x40&maptype=roadmap&sensor=false&zoom=12&key=YOURAPIKEY";  
    //echo $GMAPStaticUrl;
    $chuid = curl_init();
    curl_setopt($chuid, CURLOPT_URL, $GMAPStaticUrl);   
    curl_setopt($chuid, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($chuid, CURLOPT_SSL_VERIFYPEER, FALSE);
    $data = trim(curl_exec($chuid));
    curl_close($chuid);
    $image = imagecreatefromstring($data);

    // this is for debug to print the image
    ob_start();
    imagepng($image);
    $contents =  ob_get_contents();
    ob_end_clean();
    echo "<img src='data:image/png;base64,".base64_encode($contents)."' />";

    // here is the test : I only test 3 pixels ( enough to avoid rivers ... )
    $hexaColor = imagecolorat($image,0,0);
    $color_tran = imagecolorsforindex($image, $hexaColor);

    $hexaColor2 = imagecolorat($image,0,1);
    $color_tran2 = imagecolorsforindex($image, $hexaColor2);

    $hexaColor3 = imagecolorat($image,0,2);
    $color_tran3 = imagecolorsforindex($image, $hexaColor3);

    $red = $color_tran['red'] + $color_tran2['red'] + $color_tran3['red'];
    $green = $color_tran['green'] + $color_tran2['green'] + $color_tran3['green'];
    $blue = $color_tran['blue'] + $color_tran2['blue'] + $color_tran3['blue'];

    imagedestroy($image);
    var_dump($red,$green,$blue);
    //int(492) int(570) int(660) 
    if($red == 492 && $green == 570 && $blue == 660)
        return 1;
    else
        return 0;
}

Ответ 5

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

import ogr
from IPython import embed
import sys

drv = ogr.GetDriverByName('ESRI Shapefile') #We will load a shape file
ds_in = drv.Open("land_polygons.shp")    #Get the contents of the shape file
lyr_in = ds_in.GetLayer(0)    #Get the shape file 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=ogr.osr.SpatialReference()
point_ref.ImportFromEPSG(4326)
ctran=ogr.osr.CoordinateTransformation(point_ref,geo_ref)

def check(lon, lat):
    #Transform incoming longitude/latitude to the shapefile 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:
        # success!
        print lon, lat

check(-95,47)

Я пробовал дюжину координат, он отлично работает. Файл land_polygons.shp можно загрузить здесь, комплименты OpenStreetMaps. (Я сам использовал первую ссылку для загрузки WGS84, возможно, вторая работает также)

Ответ 6

Существует бесплатный веб-API, который решает именно эту проблему и называется onwater.io. Это не что-то встроенное в карты Google, но с учетом широты и долготы оно точно вернет истину или ложь через запрос на получение.

Пример по воде: https://api.onwater.io/api/v1/results/23.92323,-66.3

{
  lat: 23.92323,
  lon: -66.3,
  water: true
}

Пример на суше: https://api.onwater.io/api/v1/results/42.35,-71.1

{
  lat: 42.35,
  lon: -71.1,
  water: false
}

Полное раскрытие информации Я работаю в Dockwa.com, компании, которая занимается разработкой onwater. Мы построили на воде, чтобы решить эту проблему сами и помочь сообществу. Это бесплатно для использования (платят за большой объем), и мы хотели бы поделиться :)

Ответ 7

В дополнение к обратному геокодированию - как Д-р Молле указал, что он может вернуть ZERO_RESULTS - вы можете использовать службу Elevation. Если вы получите нулевые результаты по обратному геокодированию, получите высоту местоположения. Как правило, море получает отрицательное число, поскольку дно моря находится ниже уровня моря. Там полностью обработанный пример службы высот в http://www.daftlogic.com/sandbox-google-maps-find-altitude.htm.

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

Ответ 8

Этот метод абсолютно ненадежен. Фактически, возвращаемые данные будут полностью зависеть от того, в какой части мира вы работаете. Например, я работаю во Франции. Если я нажму на море на побережье Франции, Google вернет ближайший участок, где он может "угадать". Когда я запросил информацию от Google по этому же вопросу, они ответили, что не могут точно вернуть, что запрашиваемая точка была на водной массе.

Не очень удовлетворительный ответ, я знаю. Это довольно сложно, особенно для тех из нас, кто предоставляет пользователю возможность щелкнуть по карте, чтобы определить положение маркера.

Ответ 9

Если все остальное не удастся, вы всегда можете попробовать проверить высоту в точке и на некоторое расстояние - не многие вещи, кроме воды, как правило, полностью плоские.

Ответ 10

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

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

Надеюсь, что это поможет в некотором роде.

Ответ 11

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

Это можно сделать с помощью двоичных файлов GDAL, источника C или с помощью swig в Java, Python и т.д.

Карты переписи

Информация GDAL

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

Ответ 12

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

Как вы можете видеть, идеа в основном такая же, как 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");
    }
});

Ответ 14

Мне удалось приблизиться, используя API Elevation Google. Здесь изображение результатов:

screenshot of results

Вы видите, что шестиугольники в значительной степени остаются на суше, хотя определен прямоугольный периметр, который проходит частично над водой. В этом случае я сделал быструю проверку с Карт Google, и минимальная высота на суше составляла около 8-9 м, так что это был мой порог. Код в основном копируется/вставляется из документации Google и, здесь полный текст:

https://gist.github.com/dvas0004/fd541a0502528ebfb825

Ответ 15

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

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


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


Шаги по извлечению имени океана:

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

2.) Если Google возвращает нулевые результаты, вероятность того, что координата лежит над океаном, составляет 99%. Теперь сделайте вторичный запрос обратного геокодирования с теми же координатами, что и для Яндекса. Yandex вернет ответ 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 ярдов), затем выполните запрос вторичной резервной копии с помощью Yandex и проверьте, чтобы увидеть значение "вид", если оно "гидро" , тогда вы знаете, что координата лежит на воде. Поскольку Google вернул результат в отличие от приведенного выше примера, это 99,99%, вероятно, это внутренний водный поток воды, поэтому теперь вы можете получить имя. Если "вид" не является "гидро" , используйте геокодированный объект 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. Однако у Yandex очень гибкое лицензирование, и вы можете использовать их данные для отображения на картах Google.

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

Ответ 16

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

Инициализировать приведенный ниже список

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{ }

Ответ 17

Как полный новичок в 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 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 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.

Ответ 18

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

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

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

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