..そしてGoogleマップは「水から水を分ける」
まあ、聖書の意味ではなく….
[Lat、Lon]のポイントが陸か水かを確認するために、どのようなオプションがあるのか知りたいのですが。
Google Mapsには明らかにこのデータがあります(水域は青です)が、APIにはそのために使用できるものがありますか?そしてそうでない場合-彼らはそれを考えたことがないので、彼らはそれを提供していませんか?それとも複雑すぎるから?
ここでいくつかの同様の質問(地形や標高の種類を見つけるなど)を除いて、この問題に関する情報は見つかりませんでしたが、正確に必要なものではありません。
そのための分離層はありますか?オプション?コマンド?または、手動でそれを行う必要がありますか?
私がこれにアプローチする方法を考えることができる唯一の方法(手動で行う必要があります)は、提供されるすべてのタイルの正確なポイントを確認し、そのGoogleマップの色相のRGB値を確認することです。これは理論上です-実際には-それを達成する方法がわからないため、最初の障害は、タイル上のピクセル位置を[LatLon]ポイントに変換する方法がわからないことです
既製のソリューションがはるかに簡単になります。
私は世界のすべての水を必要としないことに注意してください(たとえば、小川、小さな池、ほとんどの川、またはあなたの隣人のプールは気にしません。水上車両の助けを借りずに冒険できるポイントが必要です。 )
EDIT I
コメントを読んだ後:標高方法は信頼性が低く、海面下の場所が多すぎます(ここで "最も深い" 10のリストを見ることができます http://geology.com/below-sea-level / )そして、海面(湖)の上の陸地水域が多すぎます。逆ジオロケーション方法は、都市、州などの地政学的エンティティ、またはゼロを何度も返すため、信頼できません。質問をする前に、これらの擬似解決策を既に検討しましたが、実際に質問に答えた人はいませんでした。これらの方法は、せいぜい悪い「推測」です。
これらは2つの異なる方法です。試してみてください:
Google Maps Reverse Geocoding を使用できます。結果セットでは、types
をチェックすることで水かどうかを判断できます。ウォーターズの場合、タイプはnatural_feature
です。このリンクで詳細を確認してください http://code.google.com/apis/maps/documentation/geocoding/#Types 。
また、Sea, Lake, Ocean
と、水に関連するその他の単語が含まれている場合は、より正確に機能の名前を確認する必要があります。たとえば、砂漠もnatural_feature
sです。
Prons-すべての検出プロセスはクライアントのマシンで実行されます。独自のサーバー側サービスを作成する必要はありません。
短所-非常に不正確で、水域で「なし」になる可能性が非常に高い。
Google Static Maps を使用して、ピクセルで水/土地を検出できます。ただし、この目的のために、httpサービスを作成する必要があります。
サービスで実行する必要がある手順は次のとおりです。
latitude
、longitude
およびcurrent zoom
を受信します。http://maps.googleapis.com/maps/api/staticmap?center={
latitude,
longitude}&zoom={
current zoom`}&size = 1x1&maptype = roadmap&sensor = falseリクエストをGoogle Static Mapサービスに送信します。クライアント側ではピクセルの色を検出できません。はい、クライアントのマシンに静的イメージをロードし、canvas
要素にイメージを描画できます。ただし、キャンバスのコンテキストのgetImageData
を使用してピクセルの色を取得することはできません。これは、クロスドメインポリシーによって制限されています。
Prons-非常に正確な検出
短所-検出のための独自のサーバーリソースの使用
現在のGoogleサービスでは不可能なようです。
ただし、Koordinates Vector JSON Query serviceなどの他のサービスもあります! URLのデータをクエリするだけで、JSON/XML応答が返されます。
キーと選択したレイヤー番号を登録して提供する必要があります。すべての 利用可能なレイヤーのリポジトリ を検索できます。ほとんどのレイヤーは地域限定ですが、 World Coastline のようにグローバルを見つけることもできます。
レイヤーを選択したら、「サービス」タブをクリックすると、リクエストURLの例が表示されます。登録するだけでいいと思います!
そして今最高:
すぐには利用できません。どうにかして処理する必要がありますが、動作するはずです!レイヤーリポジトリは、実際、人々が必要に応じてアップロードしたように見えます。
これは私が使用しているものであり、それほど悪くはありません...ピクセルを追加することで無駄にする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;
}
この記事をご覧ください。サーバーを必要とせずに、何かが水上にあるかどうかを正確に検出します。これは、Googleマップのカスタムスタイル機能に依存するハックです。
http://tech.bellycard.com/blog/where-d-the-water-go-google-maps-water-pixel-detection-with-canvas/
このクエリをローカルで実行する方が面白いと思ったので、より自立できる可能性があります:一度に25000のランダムな土地座標を生成したいとします。コストのかかる外部APIへの呼び出しを避けたいと思います。これは、TomSchoberが言及した python example を使用して、これをPythonで撮影したものです。基本的には、すべての土地座標を含む 既製の350MBファイル で座標を検索し、座標がそこに存在する場合、それらを印刷します。
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)
十数個の座標を試してみましたが、うまく機能します。 「land_polygons.shp」ファイルをダウンロードできます ここ 、OpenStreetMapsの賛辞。 (私は最初のWGS84ダウンロードリンクを自分で使用しましたが、2番目の作品も同様です)
onwater.io と呼ばれるこの問題を正確に解決する無料のWeb APIがあります。 Googleマップに組み込まれているものではありませんが、緯度と経度を指定すると、getリクエストを介してtrueまたはfalseを正確に返します。
水の例: https://api.onwater.io/api/v1/results/23.92323,-66.
{
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 で働いています。この問題を自分で解決し、コミュニティを支援するために、私たちは水上に構築しました。無料で使用できます(大量に支払われる)。共有したいと思いました:)
Dr Molle が指摘したように、逆ジオコーディングに加えて、ZERO_RESULTSを返す場合があります-標高サービスを使用できます。逆ジオコーディングによって結果がゼロになる場合は、場所の標高を取得します。一般に、海底が海面より下にあるため、海は負の数になります。 http://www.daftlogic.com/sandbox-google-maps-find-altitude.htm に高度サービスの完全に機能する例があります。
Googleはこの情報を利用できないため、他の方法は単なる推測であり、推測は本質的に不正確であることに注意してください。ただし、リバースジオコーディングによって返されるtype
を使用するか、type
が利用できない場合は標高を使用することで、ほとんどの場合に対応できます。
他のすべてが失敗した場合は、常にその地点とある程度の距離で標高を確認してみてください-水以外のものが完全に平らになる傾向はほとんどありません。
この方法はまったく信頼できません。実際、返されるデータは、作業している世界のどの部分に完全に依存します。たとえば、私はフランスで働いています。フランスの海岸の海をクリックすると、Googleは「推測」できる最も近いLANDの場所を返します。この同じ質問に対してGoogleに情報を要求したとき、彼らは、水塊で要求したポイントを正確に返すことができないと答えました。
非常に満足のいく答えではありません。これは、ユーザーが地図上でクリックしてマーカーの位置を定義できる機能を提供するユーザーにとっては特にイライラさせられます。
同様の質問に対する回答を参照 -Earth Apiの「HIT_TEST_TERRAIN」を使用して機能を実現します。
私がここにまとめたアイデアの実例があります: http://www.msa.mmu.ac.uk/~fraser/ge/coord/
残念ながら、この回答はGoogle Maps API内になく、参照されているリソースは無料ではありませんが、緯度/経度のペアを受け入れる操作GetWaterOrLand
を公開するDynamicGeometryによって提供されるWebサービスがあります( ここでデモを見ることができます )。
これがどのように実装されるかについての私の理解は、水体形状ファイルを使用することです。これらのシェイプファイルがGoogle Maps APIでどのように使用されているかはわかりませんが、リンクされたデモからある程度の洞察を得られるかもしれません。
それが何らかの形で役立つことを願っています。
Google Elevation APIを使用することで、なんとか近づきました。結果の画像を次に示します。
部分的に水上を通る長方形の境界が定義されている場合でも、六角形はほとんど陸地にとどまっています。この場合、Googleマップ自体から簡単に確認しましたが、地上の最低標高は約8〜9mでした。コードの大部分は、GoogleのドキュメントとStack Overflowからコピー/貼り付けされています。完全な要点は次のとおりです。
ここで独自のロールをお勧めします。 [〜#〜] gdal [〜#〜] などのツールを使用して、シェープファイル内のポイントの下のコンテンツを照会できます。 S Census Burea を含む多くのソースから米国地理のシェープファイルを取得できます。
これは、GDALバイナリ、ソースC、またはJava、Pythonなどのswigを介して実行できます。
純粋なJavaScriptの別の例を次に示します。 http://jsfiddle.net/eUwMf/
ご覧のとおり、ideiaは基本的にrebe100xと同じで、Google静的マップAPIから画像を取得し、最初のピクセルを読み取ります。
$("#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");
}
});
_List<Address>
_ addressが0を返す場合、この場所をoceanまたはNatural Resourcesと見なすことができます。GooglePlaces API応答の応答メソッドに以下のコードを追加するだけです。
前述のリストの下に初期化
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{ }
Googleは、海または内陸の水域のいずれかにある座標に関して信頼できる結果を提供しないため、Yandexなどの別のバックアップサービスを使用して、不足している重要な情報を提供する必要があります。 Googleは世界のデータの信頼性と完全性においてはるかに優れているため、Yandexをプライマリジオコーダーとして使用することはほとんどありませんが、Yandexは水域の座標に関連するデータを取得するために非常に役立ちます。両方を使用してください。
Yandexドキュメント: https://api.yandex.com.tr/maps/doc/geocoder/desc/concepts/input_params.xml
1.)最初にGoogleを使用して、座標を逆ジオコーディングします。
2.)Googleがゼロの結果を返す場合、座標が海の上にある可能性は99%です。次に、Yandexと同じ座標で2番目の逆ジオコーディングリクエストを作成します。 Yandexは、正確な座標のJSON応答を返します。この応答内には、重要度の2つの「キー」:「値」のペアがあります
["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["kind"]
and
["GeoObject"]["name"]
Kindキーをチェックします。== "水力"の場合、水域を超えていることがわかります。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%が内陸の水域である可能性が高いため、名前を取得できます。 「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が提供する以外の地図にデータを表示することを許可していません。ただし、Yandexには非常に柔軟なライセンスがあり、そのデータを使用してGoogleマップに表示できます。
また、Yandexには50,000リクエスト/日という高いレート制限があり、APIキーは不要です。
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に固執しようとする悪夢がありました。