Verify if a point is Land or Water in Google Maps
Asked Answered
G

21

116

..and then Google-maps "divide the waters from the waters"

Well, not in the biblical sense but..

I would like to know what options I have in order to verify if a point of [Lat, Lon] is Land or Water.

Google Maps obviously has this data (the bodies of water are blue) - but is there something in the API that I can use for that? And if not - are they not serving it because they never thought of it? Or because it is too complicated?

I have not found any info on the matter - except some similar questions here (like finding type of terrain, or elevation - but it is not exactly what I need).

Is there separated layer for that? An option? Command? Or should I go to do that manually?

The only way that I can think of how to approach this (should I need to do that manually) is to check every served tile for the exact point - and then check RGB value for that Google map hue. This is only on theory - because in practice - I have no idea how to accomplish that, the first obstacle being that I do not know how I can convert a pixel location on a tile to [LatLon] point for example

A ready made solution would be much easier.

Note that I do not need ALL the water in the world (for example - I do not care about streams, small ponds, most rivers or your neighbor's swimming pool. I need the points where a person can venture without the aid of a floating vehicle)

EDIT I

After reading comments: The elevation method is not reliable, there are too many places BELOW sea-level (you can see a list of the "deepest" 10 here http://geology.com/below-sea-level/ ) and there are too many land-locked water bodies ABOVE sea level (lakes). The reverse geolocation method is not reliable because it will return a Geo-political entity, like city, or state - or ZERO many times. I have already looked into those pseudo-solutions before asking the question - but none of them actually answered the question - those methods are bad "guessing" at best.

Gast answered 10/3, 2012 at 6:33 Comment(6)
You might be able to use the elevation library. While it doesn't always hold true, I imagine that most of the time things at sea level area water. There are some rather obvious corner cases (Death Valley CA, the Netherlands, lakes in mountains, etc.) but it might work for a rough approximation.Myron
thanks, I have already thought of that - but like you pointed out - there are too many point below sea level on earth - excluding all of them is not a viable solution..Gast
@michael - not to mention all the land-locked water-bodies that you mentioned .. (lakes etc..)Gast
Maybe better fit for GIS.SE? You can migrate when the bounty ends.Attu
As you have received answer, I have nothing to say on that.. But, If looking for water data, or GIS information, well there is a separate discussiong going on on our separate domain http://gis.stackexchange.com/ Here, you will find many thing you may require, including water data.. that will help you in case..(if required.. ) Old Post I hope this will help ..Aristophanes
See also #8362755Selby
E
56

These are 2 different ways, you may try:

  • You can use Google Maps Reverse Geocoding . In result set you can determine whether it is water by checking types. In waters case the type is natural_feature. See more at this link http://code.google.com/apis/maps/documentation/geocoding/#Types.

    Also you need to check the names of features, if they contain Sea, Lake, Ocean and some other words related to waters for more accuracy. For example the deserts also are natural_features.

    Pros - All detection process will be done on client's machine. No need of creating own server side service.

    Cons - Very inaccurate and the chances you will get "none" at waters is very high.

  • You can detect waters/lands by pixels, by using Google Static Maps. But for this purpose you need to create http service.

    These are steps your service must perform:

    1. Receive latitude,longitude and current zoom from client.
    2. Send http://maps.googleapis.com/maps/api/staticmap?center={latitude,longitude}&zoom={current zoom`}&size=1x1&maptype=roadmap&sensor=false request to Google Static Map service.
    3. Detect pixel's color of 1x1 static image.
    4. Respond an information about detection.

    You can't detect pixel's color in client side. Yes , you can load static image on client's machine and draw image on canvas element. But you can't use getImageData of canvas's context for getting pixel's color. This is restricted by cross domain policy.

    Prons - Highly accurate detection

    Cons - Use of own server resources for detection

Emeldaemelen answered 10/3, 2012 at 7:42 Comment(8)
Thanks - I have already checked it - I did not know that the types are turning Sea Lake Ocean and the likes, and like you pointed in your edit - natural_feature would also be a mountain, an island, and a desert .. Can you maybe point to a documentation ? also - how can you do a reverse geocoding for places without addresses ? and what about a lake that is a part of a geoploitical entity ? like a lake INSIDE a city or municipality limit (for example genevre ) or simply a point wich is INSIDE a city port .In my trials I have faild to do so..Gast
For the most of the water in the world a reverse geocoding will return "zero results", check out the geocoding-tool: gmaps-samples-v3.googlecode.com/svn/trunk/geocoder/… and click somewhere inside an ocean.Scorn
@Attu - not that I want to be ungreatefull or unrespectfull for fellow "stackers" - but maybe it is not voted because it is not valid / accurate method ?Gast
@ObmerkNinenine Hmm..Indeed Google Maps are not very precise at reverse geocoding, when it is related to waters. I apologize for my inaccuracies. However I have found another solution for your problem.Please check it out on my updated answer.Emeldaemelen
Using Static Maps in the way proposed would probably be held to be in breach of the Terms (10.1.1(h)).Armillary
Reverse Geocoding will not return water bodies, so forget about that.Illuminative
As for the Static Maps approach, you can do it with style developers.google.com/maps/documentation/static-maps/… but might as well use the article Saurav linked.Illuminative
never get type as natural_feature anymore,Operable
A
19

It doesn't seem possible with any current Google service.

But there are other services, like Koordinates Vector JSON Query service! You simply query the data in the URL, and you get back a JSON/XML response.

Example request: 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

You have to register and supply your key and selected layer number. You can search all their repository of available layers. Most of the layers are only regional, but you can find global also, like the World Coastline:

enter image description here

When you select a layer, you click on the "Services" tab, you get the example request URL. I believe you just need to register and that's it!

And now the best:

You can upload your layer!

It is not available right away, hey have to process it somehow, but it should work! The layer repository actually looks like people uploaded them as they needed.

Attu answered 28/6, 2013 at 16:4 Comment(6)
this looks almost perfect, however I don't see any local maps that are not of Oceania. Are there any US layers?Metts
@Metts the layer I mentioned is global. And you can also search the layers by region.Attu
@Metts I just noticed you can upload your own layer! See my update.Attu
Hey, Tomas, I don't know whether you actually got the bounty or not (since I was offline for a week) but this is awesome! Thank you for your help, I wouldn't have been able to get my application to work. Thanks! (If you didn't get the bounty, I'll reaward it, just PM me)Metts
Hey, you saved me a week of custom coding! It's worth it!Metts
So, did you actually manage to implement this solution? Which layer did you use for it? Is it freely available? I think many people will be interested in the details of your solution, @Metts !Attu
V
15

There is a free web API that solves exactly this problem called onwater.io. It isn't something built into Google maps, but given a latitude and longitude it will accurately return true or false via a get request.

Example on water: https://api.onwater.io/api/v1/results/23.92323,-66.3

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

Example on land: https://api.onwater.io/api/v1/results/42.35,-71.1

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

Full disclosure I work at Dockwa.com, the company behind onwater. We built onwater to solve this problem ourselves and help the community. It is free to use (paid for high volume) and we wanted to share :)

Verminous answered 18/7, 2017 at 3:26 Comment(7)
Updated Example Links: Water Example: api.onwater.io/api/v1/results/23.92323,-66.3 Land Example: api.onwater.io/api/v1/results/42.35,-71.1Exemption
It's not free any more (for higher volumes), but if it does the job it's still very affordable!Exemption
The documentation page gives an error. I wanted to check if there was any coverage specific data? I mean which countries do you cover?Richella
Does onwater.io work for lakes and rivers? If so, do I get an indication of the type?Berni
Lol not code related at all but I'd like to extend my full props to you guys for building this. This is so out there (pun intended) I am totally incapable of imagining how the idea of turning this into a $/call came up. EDIT: I assumed dockwa.com had to do with containers. These guys are actually in the boat business. LOLResolute
Unfortunately, the OnWater.io homepage says that the API is shutting down December 2nd, 2022. IsItWater.com was created by the same developer and provides the same functionality.Accent
I put together an open source version of IsItWater that can be self hosted github.com/dillonstreator/is-on-water. I also created a quick-deploy template on railway.app railway.app/template/MfUYQX?referralCode=ToZEjF.Depreciable
G
11

I thought it was more interesting to do this query locally, so I can be more self-reliant: let's say I want to generate 25000 random land coordinates at once, I would rather want to avoid calls to possibly costly external APIs. Here is my shot at this in python, using the python example mentionned by TomSchober. Basically it looks up the coordinates on a pre-made 350MB file containing all land coordinates, and if the coordinates exist in there, it prints them.

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)

I tried a dozen coordinates, it works wonderfully. The "land_polygons.shp" file can be downloaded here, compliments of OpenStreetMaps. (I used the first WGS84 download link myself, maybe the second works as well)

Geosyncline answered 19/12, 2014 at 11:0 Comment(3)
What about lakes? Does it regard points on lakes as sea or land?Fussy
Good question! I checked on the page to the OpenStreetMaps data that was linked in my answer, and it says that the lands file bases its values on the tag natural=coastline. A quick googling gives use this page which specifically states that coastline tags actually do not apply to lakes in their nomenclature. So I would say that no, my method does not identify lakes as water, since the dataset I am using does not. But try it for yourself!Geosyncline
Thhank you for this method. Managed to speedup each query 4 to 6 times, by generating spatial index for the shapefile, as described in this answer: gis.stackexchange.com/a/354702/216574Ameeameer
T
8

This what I use and it is working not too bad... you can improve the test if you have more cpu to waste by adding pixels.

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;
}
Thorianite answered 22/1, 2013 at 13:50 Comment(1)
Code doens;t work on new version. New version should be like this if($red == 537 && $green == 627 && $blue == 765)Binding
F
7

Checkout this article. It accurately detects if something is on the water without needing a server. It's a hack that relies on the custom styling feature in Google Maps.

Flocculate answered 17/9, 2013 at 23:15 Comment(0)
A
5

In addition to the reverse geocoding -- as Dr Molle has pointed out, it may return ZERO_RESULTS -- you could use the Elevation service. If you get zero results by reverse geocoding, get the elevation of the location. Generally, the sea gets a negative number as the seabed is below sea level. There's a fully-worked example of the elevation service.

Bear in mind that as Google don't make this information available any other method is just a guess and guesses are inherently inaccurate. However using the type returned by reverse geocoding, or the elevation if type is not available, will cover most eventualities.

Armillary answered 10/3, 2012 at 12:19 Comment(1)
thanks for your answer and the example link (BTW - it is not working in Opera for me) - but I can not really ignore all the areas which are land and negative and my experiments showed that the TYPE is not reliable - and many times returns a near-by geopolitical entity. there must be some more precise method - "guessing" does not seems the right approach here . If the TYPE was reliable - It would have been the best solution - but it is not ... and you are ignoring all the land-locked water bodies that are ABOVE sea level ...Gast
I
3

This method is totally unreliable. In fact, the returned data will totally depend on what part of the world you are working with. For example, I am working in France. If I click on the sea on the coast of France, Google will return the nearest LAND location it can "guess" at. When I requested information from Google for this same question, they answered that they are unable to accurately return that the point requested in on a water mass.

Not a very satisfactory answer, I know. This is quite frustrating, especially for those of us who provide the user with the ability to click on the map to define a marker position.

Irruptive answered 10/3, 2012 at 12:55 Comment(1)
I agree - the methods that were suggested by @ user1113426 and @Andrew Leach are not really methods . it is better to tell the users "do not click on the blue areas" :-) but seriously - I am very surprised that google do not want to release such a function - even if approximate - it is better then the "approximation" that exists now - that like you pointer - sometimes "snaps" to a location hundreds of meters away . Even my suggested method is more ccurate (too bad I have no idea how to accomplish this.)Gast
C
3

If all else fails you could always try checking the elevation at the point and for some distance about - not many things other than water tend to be completely flat.

Conservationist answered 4/7, 2013 at 14:4 Comment(1)
thanks, this is a nice idea , but it would fail spectacularly on every waterfall, or a river canyon...Gast
M
2

Unfortunately this answer isn't within the Google Maps API and the referenced resource is not free, but there's a web service provided by DynamicGeometry that exposes an operation GetWaterOrLand which accepts a latitude/longitude pair (you can see a demo here).

My understanding of how this is implemented is by using water body shape files. How exactly these shape files are used with the Google Maps API, but you might be able to get some insight from the linked demo.

Hope that helps in some way.

Michelle answered 17/8, 2012 at 21:46 Comment(0)
H
2

I would recommend rolling your own here. You can use tools like GDAL to query the contents under a point in a shapefile. You can get shapefiles for US geography from many sources including the US Census Bureau.

This can be done via GDAL binaries, the source C, or via swig in Java, Python, and more.

Census Maps

GDAL Information

Point Query Example in Python

Havildar answered 2/7, 2013 at 13:36 Comment(0)
T
2

Here's another example in pure JavaScript: http://jsfiddle.net/eUwMf/

As you can see, the ideia is basically the same as rebe100x, getting the image from Google static map API, and read the first pixel:

$("#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");
    }
});
Titrate answered 2/7, 2013 at 17:25 Comment(0)
S
2

See the answer I gave to a similar question - it uses "HIT_TEST_TERRAIN" from the Earth Api to achieve the function.

There is a working example of the idea I put together here: http://www.msa.mmu.ac.uk/~fraser/ge/coord/

Sutherlan answered 2/7, 2013 at 17:33 Comment(0)
U
2

If List<Address> address returns 0 , you can assume this location as ocean or Natural Resources.Just add Below Code in Your response Method of Google Places API Response.

Initialize Below List as mentioned

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

Uzial answered 27/5, 2017 at 11:4 Comment(0)
J
1

Here is a simple solution

Because Google does not provide reliable results with regards to coordinates that lay on either ocean or inland bodies of water you need to use another backup service, such as Yandex, to help provide that critical information when it is missing. You most likely would not want to use Yandex as your primary geocoder because Google is far superior in the reliability and completeness of the worlds data, however Yandex can be very useful for the purpose of retrieving data when it relates to coordinates over bodies of water, so use both.


Yandex Documentation: https://api.yandex.com.tr/maps/doc/geocoder/desc/concepts/input_params.xml


The steps to retrieve Ocean name:

1.) Use Google first to reverse geocode the coordinate.

2.) If Google returns zero results, it is 99% likely the coordinate lies over an ocean. Now make a secondary reverse geocoding request with the same coordinates to Yandex. Yandex will return a JSON response with for the exact coordinates, within this response will be two "key":"value" pairs of importance

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

and

["GeoObject"]["name"]

Check the kind key, if it == "hydro" you know you are over a body of water, and because Google returned zero results it is 99.99% likely this body of water is an ocean. The name of the ocean will be the above "name" key.

Here is an example of how I use this strategy written in Ruby

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

The steps to retrieve an Inland Body of Water name:

For this example assume our coordinate lies in a lake somewhere:

1.) Use Google first to reverse geocode the coordinate.

2.) Google will most likely return a result that is a prominent default address on land nearby. In this result it supplies the coordinates of the address it returned, this coordinate will not match the one you provided. Measure the distance between the coordinate you supplied and the one returned with the result, if it is significantly different (for example 100 yards) then perform a secondary backup request with Yandex and check to see the value of the "kind" key, if it is "hydro" then you know the coordinate lies on water. Because Google returned a result as opposed to the example above, it is 99.99% likely this is an inland body of water so now you can get the name. If "kind" does not == "hydro" then use the Google geocoded object.

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

and

["GeoObject"]["name"]

Here is the same code written in Ruby to get inland_body_of_water

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

A note about Licensing: As far as I know Google does not allow you to use their data to display on any other maps other than those Google offers. Yandex however has very flexible licensing, and you can use their data to be displayed on Google maps.

Also Yandex has a a high rate limit of 50,000 request / day free of charge, and with no required API key.

Jurisprudent answered 18/5, 2015 at 20:1 Comment(0)
M
1

I managed to get quite close by using the Google Elevation API. Here's an image of the results:

screenshot of results

You see the hexagons pretty much stay on land even though a rectangular perimeter is defined that goes partly over water. In this case I did a quick check from Google Maps itself and the minimum elevation on land was about 8-9m so that was my threshold. The code is mostly copy/pasted from Google documentation and Stack Overflow, here's the full gist:

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

Morrissey answered 1/3, 2016 at 16:31 Comment(2)
Just FYI, Google Elevation API documentation can be found here: developers.google.com/maps/documentation/javascript/elevationMorrissey
this is a great example of possible use. but it will gloriously fail on land-lock bodies of water ( Lago di garda - Italy in the linked image example ) . Very nice code thought to be used as a possible basis for another solution !Gast
B
0

As a complete novice to Python I couldn't get SylvainB's solution to work with the python script that checks if coordinates are on land. I managed to figure it out however, by downloading OSGeo4W (https://trac.osgeo.org/osgeo4w/) and then installed everything I needed pip, Ipython, and checked that all the imports specified were there. I saved the following code as a .py file.

Code to check if coordinates are on land

###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

I tried to get it to work in R but I had a nightmare trying to get all the packages you need to install so stuck to python.

Baumgardner answered 29/1, 2019 at 11:5 Comment(0)
M
0

Here's a typed async function that returns true or false if a lat/lng is water or not. No need to pay for external api's. You must enable static maps on google cloud though.

async function isLatLngWater(lat: number, lng: number) {
  return new Promise<boolean>((resolve) => {
    const img = new Image();
    img.crossOrigin = "Anonymous";
    img.onload = () => {
      const canvas = document.createElement("canvas");
      const ctx = canvas.getContext("2d");

      ctx!.drawImage(img, 0, 0);

      const { data } = ctx!.getImageData(10, 10, 1, 1);

      if (data[0] == 156 && data[1] == 192 && data[2] == 249) {
        canvas.remove();
        resolve(true);
      } else {
        canvas.remove();
        resolve(false);
      }
    };

    img.src =
      "https://maps.googleapis.com/maps/api/staticmap?center=" +
      lat +
      "," +
      lng +
      "&size=40x40&maptype=roadmap&sensor=false&zoom=20&key=" +
      import.meta.env.VITE_GM_MSTAT;
  });
}
Mononuclear answered 7/9, 2022 at 11:20 Comment(0)
A
0

There an API service called IsItWater.com which will let you check:

Request

curl 'https://isitwater-com.p.rapidapi.com/?latitude=41.9029192&longitude=-70.2652276&rapidapi-key=YOUR-X-RAPIDAPI-KEY'

Response

{
    "water": true,
    "latitude": 41.9029192,
    "longitude": -70.2652276
}
Accent answered 11/11, 2022 at 20:21 Comment(0)
S
0

If you use javascript, I implemented the solution using Google Maps Static API as an npm package. Check it out here:

https://www.npmjs.com/package/is-it-water

Here's the main snippet but I would recommend you just install the package and follow its instructions:

async function isItWater(lat, lon, google_map_access_token) {
    return new Promise((res, rej) => {
        const url = "https://maps.googleapis.com/maps/api/staticmap?"
            + "center=" + lat + "," + lon
            + "&zoom=14"
            + "&size=1x1"
            + "&style=feature:water|color:0xFFFFFF"
            + "&style=feature:road|visibility:off"
            + "&style=feature:poi|visibility:off"
            + "&style=feature:transit|visibility:off"
            + "&style=feature:administrative|visibility:off"
            + "&style=feature:landscape|visibility:off"
            + "&key=" + google_map_access_token;

        http.get(url, response => {
            response
                .pipe(new PNG({ filterType: 4 }))
                .on('parsed', function() {
                    res(this.data[0] == 255);
                })
                .on('error', function(err) {
                    const errorMessage = "Failed to check water. Make sure your google access token has permissions to google map static.";
                    console.error(errorMessage);
                    rej({ message: errorMessage});
                });
        })
    });
}
Substantialism answered 16/6, 2023 at 9:26 Comment(0)
A
-3

I have a different solution here. In current google map implementation, it does not calculate direction/distance from a water location to land location and vice versa. Why dont we use this logic to determine if the point is land or water.

For example lets take this example

if we want to determine, if a point x is land or water, then

let us check the direction between point x and a known point y which is land. If it determines the direction/distance then point x is land or else it is water.

Ascogonium answered 4/7, 2013 at 12:1 Comment(2)
Have you actually tried it or are you just assuming, "cooking from water"?Attu
And how do you suppose to handle bridges ? or tunnels ?Gast

© 2022 - 2024 — McMap. All rights reserved.