On my webapp, I have a page with a Google Map. On the map I want the user to be able to click anywhere in the world, take the lat/long returned by the click event, and using the Google Maps API geocoding service reverse geocode it as is shown here to return whatever information Google has about that location. In the case of towns, streets, and countries; this works very well, but it does not work well for natural landmarks like oceans, rivers, etc. If you try to Reverse Geocode a lat and long in the middle of a lake , it will return information like the what county or state the lake is located in rather than the name of the Lake, which would be more helpful in my situation. To be more explicit, if I give a lat/lng in the middle of Lake Michigan, the reverse geocoding will return: "Mason County, MI, USA" rather than "Lake Michigan". However, if I click on a spot in the middle of Lake Michigan on https://www.google.com/maps, it will create a marker labeled "Lake Michigan".
Is there a google maps api service that I should be using besides the Geocode Service that will return Lake Michigan instead of "Mason County, MI, USA" if I give it a lat/long. Or is there another way I can get "Lake Michigan" returned from a click event without having to pass in a Lat/Long. The Places service seems to make a distinction between "natural" and "political" places (home addresses, business addresses, countries, cities, etc all seem to fall under the category of "political" places). So I am wondering if there are parameters I can pass to the Places Service from a click event that would return Places objects since the Geocode service does not seem to make the distinction between "political" and "natural" places.
Here is the code I have written so far that using the GeoCode Service:
const initMap = () => {
var map = new google.maps.Map(document.getElementById('location-map'), {
zoom: 3,
center: {lat: .433014, lng: 0.752724 }
});
var marker = new google.maps.Marker({
map: map,
anchorPoint: new google.maps.Point(0, -29)
});
var geocoder = new google.maps.Geocoder;
var infowindow = new google.maps.InfoWindow;
function geocodeLatLng(latLng) {
geocoder.geocode({'location': latLng}, function(results, status) {
console.log(results);
if (status === 'OK') {
if (results[0]) {
map.setZoom(10);
var marker = new google.maps.Marker({
position: latLng,
map: map
});
infowindow.setContent(results[0].formatted_address);
infowindow.open(map, marker);
}
}
})
}
map.addListener('click', function(e) {
geocodeLatLng(e.latLng);
});
}
The reverse geocoding ability of the Geocoding API as stated in the documentation:
The process of doing the opposite, translating a location on the map into a human-readable address, is known as reverse geocoding.
So the API not returning an address in the middle of a lake is working as intended. Similarly, the Places API is designed for finding businesses and points of interest, as answered in this bug on Google's Public Issue Tracker.
That said, there is a long-standing feature request to have the functionality added to the Geocoding API, similar to how maps.google.com returns geographic feature names such as "North Atlantic Ocean" when the map is clicked. There's no timeline if/when this will be implemented, but you can star the issue to show more interest in the feature and to receive updates.
Related
Here is a link to the same question.
I would however like to have this question answered using Google Geocode.
Can someone please provide me with the code to do the following, using Meteor and Blaze.
Enter zip code and return array of zip codes within 10 kilometers of that zip code.
Search collection users for fields profile.zipcode and display users matching zip codes in the array.
Thank you very much!
The Geocoder gets you the location from the text string, now you have to pass this location information to your places functionality. I have wrapped the google places code inside a function and call it from geocoder.
var address = '12 Crest View Ct';
geocoder.geocode({'address': address},
function(results, status) {
if(status == google.maps.GeocoderStatus.OK){
loc = results[0].geometry.location;
var bounds = new google.maps.LatLngBounds();
document.write(bounds.extend(results[0].geometry.location));
map.fitBounds(bounds);
new google.maps.Marker({
position:results[0].geometry.location,
map: map
});
place(loc); //here is the function call
}
}
);
I have been working with the Google Street View Image API and have an issue when api responds with "we have no imagery". I implemented a few solutions I found from previous posts, mostly from detecting "we have no imagery" of google maps street view static images. Here is my code:
var address = thisItem.addr + "," + thisItem.city + "," + thisItem.state + " " + thisItem.zip;
var url = "https://maps.googleapis.com/maps/api/streetview?size=500x500&location=" + address + "&heading=&pitch=&key=";
var itemLat = parseFloat(thisItem.lat);
var itemLng = parseFloat(thisItem.lng);
var sv = new google.maps.StreetViewService();
sv.getPanorama({location: {lat: itemLat, lng: itemLng}, radius: 1}, processSVData);
function processSVData(data, status) {
if (status === google.maps.StreetViewStatus.OK) {
console.log('status ok');
} else {
console.log('status not ok')
}
}
I am going to plug the url into an img src if there is a street view.
Because I am using the address and not lat lng in the url call, and lat lng in the getPanorama, when an image returns with "no imagery found" the StreetViewStatus is still OK so I am not able to set a stock image. I also changed to use the lat lng in the url and then an image will always show up even if the status is not OK. Any suggestions?
As discussed in Directly Accessing Street View Data
You may initiate two types of requests to the StreetViewService:
Request with a StreetViewPanoRequest, this returns panorama data given a reference ID which uniquely identifies the panorama. Note that these reference IDs are only stable for the lifetime of the imagery of that panorama.
Request with a StreetViewLocationRequest this searches for panorama data over a given area, given a passed LatLng.
So, for addresses that you used, I suggest that you should consider converting them using Geocoding Service.
Aside from that, these references might help you too
Using Street View Imagery
This Thread in Google Maps Help Forum
SO post - How can I tell if Google's Streetview Image API Returns “Sorry, we have no imagery here” (ie. NULL) Result?
I tried to search for all cities within a visible map's bounds. How can I do that?
Below is what I tried to do:
$.fn.gmap3.geocoder.geocode({ 'address': 'Georgia' }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
globalMap.setCenter(results[0].geometry.location);
var resultBounds = new google.maps.LatLngBounds(
results[0].geometry.viewport.getSouthWest(),
results[0].geometry.viewport.getNorthEast()
);
globalMap.fitBounds(resultBounds);
// get cities in the map
var service = new google.maps.places.PlacesService(globalMap);
var request = {
bounds: resultBounds,
types: ['locality']
};
service.search(request, function (results, status) {
debugger;
});
}
});
But the result is ZERO_RESULTS. Maybe the reason is that the results are restricted to a radius of 50.000 meters?
Anyone knows how to solve my problem? Thanks a lot.
--UPDATE--
Thank, Sean, for reading my post carefully and give detail feedback.
This is how I refer to the lib:
src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"
I also added more detail to the geocode function to get more precise result. But I still don't get the results I want.
Check the list in this page: https://developers.google.com/places/documentation/supported_types, I realize that almost all items in the first list returns values but not for the second list. The only item return value is 'political' and it returns only 1 instead of 20.
This is my code after modifing:
this.setCenterByAddress = function (address, region) {
$.fn.gmap3.geocoder.geocode({ 'address': address, 'region': region }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
globalMap.setCenter(results[0].geometry.location);
var resultBounds = new google.maps.LatLngBounds(
results[0].geometry.viewport.getSouthWest(),
results[0].geometry.viewport.getNorthEast()
);
globalMap.fitBounds(resultBounds);
// get cities in the map
var service = new google.maps.places.PlacesService(globalMap);
var request = {
bounds: resultBounds,
types: ['country',
'administrative_area_level_1',
'administrative_area_level_2',
'administrative_area_level_3',
'colloquial_area',
'country',
'floor',
'geocode',
'intersection',
'locality',
'natural_feature',
'neighborhood',
'political',
'point_of_interest',
'post_box',
'postal_code',
'postal_code_prefix',
'postal_town',
'premise',
'room',
'route',
'street_address',
'street_number',
'sublocality',
'sublocality_level_4',
'sublocality_level_5',
'sublocality_level_3',
'sublocality_level_2',
'sublocality_level_1',
'subpremise',
'transit_station']
};
service.search(request, function (results, status) {
debugger;
});
}
});
}
MORE INFO: The same value return even when location and radius is used. And I use free map and receive "OVER_QUERY_LIMIT" all the time.
You shouldn't be limited to 50,000 meters unless you use the location and radius option, which you are not; you are using bounds. I suggest backing out a level and digging into the results that are returned from the starting call to geocode, because your usage of the PlacesService appears to be correct. What are the values internal to the resultBounds object? I also notice that you aren't using region biasing when you call the geocoder and it may be that "Georgia" is not sufficiently specific. For example, do you mean the region within the Russian Federation or the US state? And I'm not sure what URL you are using to load the Google Maps API & places library, but that could also be effecting your results.
I'd double-check the results coming back from the geocoder, because unless I am missing something, it looks like your basic approach is sound.
You can't return more than two near by localities around a particular latitude-longitude with Geocoding API/Places API
Please see this thread on Google Places API forum
This is not possible with the Google Places API as political results
such as locality, neighbourhood and sublocality are returned to
identify the area of the request and are limited to two per request.
I'm sure I'm dealing with a fairly common problem that's been solved many times before.
My web application requests about 100 line-delimited addresses of buildings from another service. I must now plot all these as gmarkers on a google map (with api version 3). I must also calibrate the view port to display all the gmarkers, that is determine the map center and the appropriate zoom value.
I found some code from the Google Maps API and tweaked it to plot one point:
function codeAddress() {
var address = '1 Yonge Street, Toronto, ON';
geocoder.geocode( { 'address': address}, geocodeCallBack);
}
function geocodeCallBack(results, status)
{
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
} else {
alert("Geocode was not successful for the following reason: " + status);
}
}
However, I suspect that performing 100 asynchronous geocoding calls may be slow. Does anyone have suggestion on the best way to achieve what I need?
Performing 100 Geocodes each time your page is loaded will take tens of seconds, so I suggest geocoding in advance.
If the addresses are always the same, or rarely change, you can geocode them in advance using the Geocoding Service (http://code.google.com/apis/maps/documentation/javascript/services.html) and temporarily store the resulting Lat/Lngs on your server as long as they are only ever displayed on a Maps API map.
Temporarily means that you must update these Lat/Lngs periodically (e.g. once every 30 days).
(See 10.1.3b for details: http://code.google.com/apis/maps/terms.html)
I am using google maps Api V3 and using reverse geocoding to find the name of a country clicked on.
This appears to work fine for most countries except the countries within the UK.
The UK consists of England, Scotland, Wales and Northern Ireland, which are 4 separate countries, but google maps (and most other country things) see them all as just "UK".
I need to know which particular country within the UK has been clicked and not just that the UK has been clicked!
I am using the following javascript and I am currently just using visual studios "watch" feature to dig down into "results[1]" to see what is contained.
function initialize() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(51.8052184317649, -4.965819906250006);
var myOptions = {
zoom: 5,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
google.maps.event.addListener(map, 'click', function (event) {
if (confirm('Is this the location you would like to you for your company?')) {
geocoder.geocode({ 'latLng': event.latLng }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
}
}
});
}
});
}
If I click when the map is zoomed quite far out the country name (ie Wales) comes back with types "administrative_area_level_1" and "political" but when you zoom in it's no longer there as it just gives the address which doesn't contain "Wales".
Does anyone know how I get round this? I'm sure other Brits have come across this?
Couldn't work out how to reverse geocode to get a UK country as I think it's actually impossible!
Ended up using postcodes and working out countries by that!
Not the best, but it works for me!
UK countries are represented as administrative_area_level_1 results, look at the 2nd last result in this example (do not rely on address_components for this):
https://maps.googleapis.com/maps/api/geocode/json?&latlng=51.641033,-0.647507