Javascript 在谷歌地图中验证点是陆地还是水

Javascript 在谷歌地图中验证点是陆地还是水,javascript,google-maps,google-maps-api-3,Javascript,Google Maps,Google Maps Api 3,…然后谷歌地图“把水和水分开” 不是圣经意义上的但是 我想知道我有什么选择来验证[Lat,Lon]点是陆地还是水 谷歌地图显然有这些数据(水体是蓝色的)-但是API中有什么我可以使用的吗?如果不是的话,他们不是因为从来没有想过而提供服务吗?还是因为太复杂了 我没有找到任何关于这个问题的信息——除了一些类似的问题(比如寻找地形类型或海拔高度——但这并不是我所需要的) 有没有分离层?选择?指挥部?还是我应该手动去做 我能想到的唯一方法是(如果我需要手动这么做的话)检查每个服务的磁贴的精确点,然后检查

…然后谷歌地图“把水和水分开”

不是圣经意义上的但是

我想知道我有什么选择来验证[Lat,Lon]点是陆地还是水

谷歌地图显然有这些数据(水体是蓝色的)-但是API中有什么我可以使用的吗?如果不是的话,他们不是因为从来没有想过而提供服务吗?还是因为太复杂了

我没有找到任何关于这个问题的信息——除了一些类似的问题(比如寻找地形类型或海拔高度——但这并不是我所需要的)

有没有分离层?选择?指挥部?还是我应该手动去做

我能想到的唯一方法是(如果我需要手动这么做的话)检查每个服务的磁贴的精确点,然后检查谷歌地图色调的RGB值。 这仅仅是理论上的——因为在实践中——我不知道如何做到这一点,第一个障碍是我不知道如何将瓷砖上的像素位置转换为[LatLon]点

现成的解决方案会容易得多

请注意,我并不需要世界上所有的水(例如,我不关心小溪、小池塘、大多数河流或你邻居的游泳池。我需要的是一个人可以在不借助漂浮车辆的情况下冒险的地方)

编辑I

阅读评论后: 高程法不可靠,海平面以下的地方太多(你可以在这里看到“最深”的10个地方),海平面以上的内陆水体(湖泊)太多。 反向地理定位方法不可靠,因为它会多次返回一个地理政治实体,如城市、州或零。
在提出问题之前,我已经研究过这些伪解决方案——但没有一个真正回答了问题——这些方法充其量只是糟糕的“猜测”。

这是两种不同的方法,您可以尝试:

  • 你可以用。在结果集中,您可以通过检查
    类型
    来确定它是否是水。在waters的情况下,类型为
    natural\u feature
    。请参阅此链接的更多信息

    此外,您还需要检查要素的名称,如果它们包含
    Sea、Lake、Ocean
    ,以及其他一些与水域相关的词语,以获得更高的准确性。例如,沙漠也是自然特征

    Pros-所有检测过程都将在客户端机器上完成。不需要创建自己的服务器端服务

    缺点-非常不准确,您在waters获得“无”的几率非常高

  • 您可以使用像素检测水域/陆地。但为此,您需要创建http服务

    以下是您的服务必须执行的步骤:

  • 从客户端接收
    纬度
    经度
    当前缩放
  • 发送<代码>http://maps.googleapis.com/maps/api/staticmap?center={纬度
    经度
    }&zoom={
    当前缩放`}&size=1x1&maptype=roadmap&sensor=false请求谷歌静态地图服务
  • 检测1x1静态图像的像素颜色
  • 回复有关检测的信息
  • 您无法在客户端检测像素的颜色。是的,您可以在客户机上加载静态图像,并在
    画布上绘制图像。但不能使用画布上下文的
    getImageData
    获取像素的颜色。这受到跨域策略的限制

    Prons-高度准确的检测

    缺点-使用自己的服务器资源进行检测


除了反向地理编码——正如前面所指出的,它可能返回零结果——您还可以使用高程服务。如果通过反向地理编码得到的结果为零,则获得该位置的高程。一般来说,当海床低于海平面时,海平面为负数。这里有一个完整的立面服务


请记住,由于谷歌不提供这些信息,任何其他方法都只是猜测,猜测本身就是不准确的。但是,使用反向地理编码返回的
类型
,或者如果
类型
不可用,则使用高程将覆盖大多数可能发生的情况。

此方法完全不可靠。 事实上,返回的数据完全取决于您使用的是世界的哪个部分。 例如,我在法国工作。 如果我点击法国海岸的海洋,谷歌将返回它能“猜”到的最近的陆地位置。 当我就同一个问题向谷歌索取信息时,他们回答说,他们无法准确地返回在水团上要求的点

我知道这不是一个很令人满意的答案。
这非常令人沮丧,尤其是对于我们这些为用户提供了点击地图定义标记位置的能力的人来说。

不幸的是,这个答案不在谷歌地图API中,引用的资源也不是免费的,但是DynamicGeometry提供了一个web服务,它公开了一个接受纬度/经度对()的操作
GetWaterOrLand

我对如何实现这一点的理解是通过使用水体形状文件。这些形状文件是如何与GoogleMapsAPI一起使用的,但是您可以从链接的演示中获得一些见解


希望这在某种程度上有所帮助。

这就是我所用的,它工作得还不错。。。如果通过添加像素可以浪费更多cpu,则可以改进测试

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;
}
功能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,$GMAPStatic)
$("#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");
    }
});
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'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=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'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:
        # success!
        print lon, lat

check(-95,47)
["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["kind"]

and

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

and

["GeoObject"]["name"]
if result.data["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["kind"] == "hydro"
     inland_body_of_water = result.data["GeoObject"]["name"] 
end
{
  lat: 23.92323,
  lon: -66.3,
  water: true
}
{
  lat: 42.35,
  lon: -71.1,
  water: false
}
###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