I'm working on a mapping project that involves using Tangram (an awesome webgl mapping library) to visualize buildings on a map. The Tangram buildings come from Open Street Maps, and use OSM id's:
As fortune would have it though, my data comes from Google's Location API, which has its own id system. Using a request like:
curl https://maps.googleapis.com/maps/api/geocode/json?address=Timble-Bridge,%20Yorkshire%20Britain&key=API_KEY_HERE
one gets back (note at the bottom the place id hash):
{
"results": [
{
"address_components": [
{
"long_name": "59",
"short_name": "59",
"types": [
"street_number"
]
},
{
"long_name": "Long Lane",
"short_name": "Long Ln",
"types": [
"route"
]
},
{
"long_name": "London",
"short_name": "London",
"types": [
"postal_town"
]
},
{
"long_name": "Greater London",
"short_name": "Greater London",
"types": [
"administrative_area_level_2",
"political"
]
},
{
"long_name": "England",
"short_name": "England",
"types": [
"administrative_area_level_1",
"political"
]
},
{
"long_name": "United Kingdom",
"short_name": "GB",
"types": [
"country",
"political"
]
},
{
"long_name": "EC1A 9EJ",
"short_name": "EC1A 9EJ",
"types": [
"postal_code"
]
}
],
"formatted_address": "59 Long Ln, London EC1A 9EJ, UK",
"geometry": {
"location": {
"lat": 51.5192377,
"lng": -0.0998815
},
"location_type": "ROOFTOP",
"viewport": {
"northeast": {
"lat": 51.52058668029149,
"lng": -0.09853251970849797
},
"southwest": {
"lat": 51.51788871970849,
"lng": -0.101230480291502
}
}
},
"partial_match": true,
"place_id": "ChIJ5UYg9FMbdkgRBOslATQK-ok",
"types": [
"cafe",
"establishment",
"food",
"point_of_interest"
]
}
],
"status": "OK"
}
I'm now wondering if there's any extant database that maps OSM id's to Google location id's. If anyone knows of any such service, or any higher order mapping one can use to deterministically map OSM and Google id's to a higher-order identification service, I'd be very grateful for any insight you can offer.
No, such a database doesn't exist and it can't exist.
Such a mapping would require that:
Both data sets are open. OSM is open but Google's data isn't.
Buildings are mapped in a similar way. This is not always the case. A building in Google may consist of several buildings in OSM, and vice versa.
IDs are stable. I don't know about Google's IDs but IDs in OSM can change.
Related
I'm using the Google Places API to find the address details of a small village in India, following this documentation from Google. My https request looks as follows:
https://maps.googleapis.com/maps/api/place/findplacefromtext/json?key=MY_API_KEY&inputtype=textquery&input=Dahigaon&fields=name,geometry,address_component
My problem is that the request above returns the following error:
Error while parsing 'fields' parameter: Unsupported field name 'address_component'.
I've tried a couple of other 'field' values, and they all seem to work except for address_component. Any thoughts on what I'm doing wrong?
Figured this one out. Apparently "Place Search, Nearby Search, and Text Search requests all return a subset of the fields that are returned by Place Details requests." See here for details: LINK
address_component is one of the fields that is not supported ...
I went through the same thing a while ago, basically you should make 2 calls, the first one to:
curl --request GET \
--url 'https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=360%20Lobelia%20Rd&inputtype=textquery&key=YOUR_KEY'
this will return the following.
{
"candidates": [
{
"place_id": "ChIJCesBrxmd5ogR5kyZiY35HLI"
}
],
"status": "OK"
}
you should take the place_id and use it in a second call like this:
curl --request GET \
--url 'https://maps.googleapis.com/maps/api/place/details/json?place_id=ChIJCesBrxmd5ogR5kyZiY35HLI&key=YOUR_KEY'
this will return the following.
{
"html_attributions": [],
"result": {
"address_components": [
{
"long_name": "360",
"short_name": "360",
"types": [
"street_number"
]
},
{
"long_name": "Lobelia Road",
"short_name": "Lobelia Rd",
"types": [
"route"
]
},
{
"long_name": "St. Augustine",
"short_name": "St. Augustine",
"types": [
"locality",
"political"
]
},
{
"long_name": "St. Johns County",
"short_name": "St Johns County",
"types": [
"administrative_area_level_2",
"political"
]
},
{
"long_name": "Florida",
"short_name": "FL",
"types": [
"administrative_area_level_1",
"political"
]
},
{
"long_name": "United States",
"short_name": "US",
"types": [
"country",
"political"
]
},
{
"long_name": "32086",
"short_name": "32086",
"types": [
"postal_code"
]
},
{
"long_name": "6516",
"short_name": "6516",
"types": [
"postal_code_suffix"
]
}
],
"adr_address": "<span class=\"street-address\">360 Lobelia Rd</span>, <span class=\"locality\">St. Augustine</span>, <span class=\"region\">FL</span> <span class=\"postal-code\">32086-6516</span>, <span class=\"country-name\">USA</span>",
"formatted_address": "360 Lobelia Rd, St. Augustine, FL 32086, USA",
"geometry": {
"location": {
"lat": 29.8358907,
"lng": -81.31464799999999
},
"viewport": {
"northeast": {
"lat": 29.8372717802915,
"lng": -81.31318596970848
},
"southwest": {
"lat": 29.8345738197085,
"lng": -81.31588393029149
}
}
},
"icon": "https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/geocode-71.png",
"icon_background_color": "#7B9EB0",
"icon_mask_base_uri": "https://maps.gstatic.com/mapfiles/place_api/icons/v2/generic_pinlet",
"name": "360 Lobelia Rd",
"place_id": "ChIJCesBrxmd5ogR5kyZiY35HLI",
"reference": "ChIJCesBrxmd5ogR5kyZiY35HLI",
"types": [
"premise"
],
"url": "https://maps.google.com/?q=360+Lobelia+Rd,+St.+Augustine,+FL+32086,+USA&ftid=0x88e69d19af01eb09:0xb21cf98d89994ce6",
"utc_offset": -240,
"vicinity": "St. Augustine"
},
"status": "OK"
}
I don't know why the other way in the documentation, I imagine that at some point due to billing issues they have separated it into 2 calls.
From what I understood about billing, for every 1000 addresses searched in this way, you would be spending approximately 34 USD.
I need to get the city from a given US Zipcode, and i'm having trouble with Boroughs like Brooklyn
im using geocode:
https://maps.googleapis.com/maps/api/geocode/json?address=11214&key=KEY
it returns this results
{
"address_components": [
{
"long_name": "11214",
"short_name": "11214",
"types": [
"postal_code"
]
},
{
"long_name": "Brooklyn",
"short_name": "Brooklyn",
"types": [
"political",
"sublocality",
"sublocality_level_1"
]
},
{
"long_name": "Kings County",
"short_name": "Kings County",
"types": [
"administrative_area_level_2",
"political"
]
},
{
"long_name": "New York",
"short_name": "NY",
"types": [
"administrative_area_level_1",
"political"
]
},
{
"long_name": "United States",
"short_name": "US",
"types": [
"country",
"political"
]
}
],
"formatted_address": "Brooklyn, NY 11214, USA",
"geometry": {
"bounds": {
"northeast": {
"lat": 40.6163139,
"lng": -73.98259999999999
},
"southwest": {
"lat": 40.5788159,
"lng": -74.014775
}
},
"location": {
"lat": 40.6046106,
"lng": -73.9982756
},
"location_type": "APPROXIMATE",
"viewport": {
"northeast": {
"lat": 40.6163139,
"lng": -73.98259999999999
},
"southwest": {
"lat": 40.5788159,
"lng": -74.014775
}
}
},
"place_id": "ChIJLzmMV-BawokR4tFzc3LaBFI",
"types": [
"postal_code"
]
}
i need a way to link this to New York City, the only hint i see is
"long_name": "Brooklyn",
"short_name": "Brooklyn",
"types": [
"political",
"sublocality",
"sublocality_level_1"
]
maybe theres a way to link Brooklyn as a sublocality of NYC but i couldn't find it.
This is a tricky example. First of all you should be aware that Geocoding API returns in address components array only components used for address formatting. In case of New York city the address formatting is very specific. It is used sublocality_level_1 instead of locality to format the addresses.
This fact is mentioned in the official documentation of Google Maps API.
Note that you might need to use a different set of components to align with the postal address formats used in some regions. For example, the sample code selects the locality component, which often represents the city part of the address. Examples of how components can differ include:
In the UK and in Sweden, the component to display the city is postal_town.
In Japan, components differ across prefectures.
Brooklyn and other parts of New York City do not include the city as part of the address. Instead, they use sublocality_level_1.
source: https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/javascript/examples/places-autocomplete-addressform
The only workaround I can think of is using a two requests:
the first request for postal code and country to get coordinate of the postal code center
the second request is reverse geocoding for coordinate from the first request with type locality
E.g.
let's get coordinate of the postal code 11214
https://maps.googleapis.com/maps/api/geocode/json?components=postal_code%3A11214%7Ccountry%3AUS&key=YOUR_API_KEY
it will return coordinate in response as
"geometry":{
"location":{
"lat":40.6046106,"lng":-73.9982756
},
...
}
Now reverse geocode the coordinate with result type locality
https://maps.googleapis.com/maps/api/geocode/json?latlng=40.6046106%2C-73.9982756&result_type=locality&key=YOUR_API_KEY
it will return New York, so this way you can relate a postal code and New York city
{
"plus_code":{
"compound_code":"J232+RM New York, NY, USA","global_code":"87G8J232+RM"
},
"results":[
{
"address_components":[
{
"long_name":"New York",
"short_name":"New York",
"types":[
"locality","political"
]
},
{
"long_name":"New York",
"short_name":"NY",
"types":[
"administrative_area_level_1","political"
]
},
{
"long_name":"United States",
"short_name":"US",
"types":[
"country","political"
]
}
],
"formatted_address":"New York, NY, USA",
"geometry":{
"bounds":{
"northeast":{
"lat":40.9175771,"lng":-73.70027209999999
},
"southwest":{
"lat":40.4773991,"lng":-74.25908989999999
}
},
"location":{
"lat":40.7127753,"lng":-74.0059728
},
"location_type":"APPROXIMATE",
"viewport":{
"northeast":{
"lat":40.9175771,"lng":-73.70027209999999
},
"southwest":{
"lat":40.4773991,"lng":-74.25908989999999
}
}
},
"place_id":"ChIJOwg_06VPwokRYv534QaPC8g",
"types":[
"locality","political"
]
}
],
"status":"OK"
}
I hope this helps!
I have a problem relating to photo, rate extraction from Google Map API.
The problem is that when I made right request I receive a response without photo\rate data inside.
Example of request:
https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJvaXwAwVWwokRvmAdVdWrD4s&key=[YOUR KEY]
The response:
"html_attributions": [],
"result": {
"address_components": [
{
"long_name": "325",
"short_name": "325",
"types": [
"street_number"
]
},
{
"long_name": "Orient Way",
"short_name": "Orient Way",
"types": [
"route"
]
},
{
"long_name": "Lyndhurst",
"short_name": "Lyndhurst",
"types": [
"locality",
"political"
]
},
{
"long_name": "Bergen County",
"short_name": "Bergen County",
"types": [
"administrative_area_level_2",
"political"
]
},
{
"long_name": "New Jersey",
"short_name": "NJ",
"types": [
"administrative_area_level_1",
"political"
]
},
{
"long_name": "United States",
"short_name": "US",
"types": [
"country",
"political"
]
},
{
"long_name": "07071",
"short_name": "07071",
"types": [
"postal_code"
]
},
{
"long_name": "2008",
"short_name": "2008",
"types": [
"postal_code_suffix"
]
}
],
"adr_address": "<span class=\"street-address\">325 Orient Way</span>, <span class=\"locality\">Lyndhurst</span>, <span class=\"region\">NJ</span> <span class=\"postal-code\">07071-2008</span>, <span class=\"country-name\">USA</span>",
"formatted_address": "325 Orient Way, Lyndhurst, NJ 07071, USA",
"geometry": {
"location": {
"lat": 40.80528109999999,
"lng": -74.1147282
},
"viewport": {
"northeast": {
"lat": 40.80654243029149,
"lng": -74.1131421697085
},
"southwest": {
"lat": 40.80384446970849,
"lng": -74.1158401302915
}
}
},
"icon": "https://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png",
"id": "916e480f4ad34516acae418957c8c75e6bb6deea",
"name": "325 Orient Way",
"place_id": "ChIJvaXwAwVWwokRvmAdVdWrD4s",
"reference": "ChIJvaXwAwVWwokRvmAdVdWrD4s",
"scope": "GOOGLE",
"types": [
"premise"
],
"url": "https://maps.google.com/?q=325+Orient+Way,+Lyndhurst,+NJ+07071,+USA&ftid=0x89c2560503f0a5bd:0x8b0fabd5551d60be",
"utc_offset": -300,
"vicinity": "Lyndhurst"
},
"status": "OK"
}
The address of this place is: 325 ORIENT WAY, LYNDHURST, NJ, 07071.
If you try to find this address in Google Map, you will find the place with list of places, like this:
After that, if you select the first item from underlined list from previous photo you will find the place with photos and rates, like this:
The link on first screenshot of place: Google Map place link.
Questions:
What do you think, is it smth wrong in my request? (following Google Map API documentation, i could not find any issues regarding the request);
As you may see on my first screenshot, we have a list with locations and only second one have photos\rate. Can it be the case that Google Map API select the first one, does not see photos\rates and just remove it from the response? But if so, I don't know how to change my request in order to select first locale with photos\rates or launch it in more flexible way.
Thank you for your help!
I found what is the problem.
The problem in place ID. In the request I used place ID for business (you can check the "type" of the response). It means that in the request i linked on object which have some location-items inside. And this obkject does not have any data like photo\rate.
I found that way how to extract the right place ID.
If you have the address of this object (in my case, the address is: 325 ORIENT WAY, LYNDHURST, NJ, 07071) and the name of the shop which you looking for (in my case it is: Frank's GMC) you can create the next two request. First - in order to extract the place ID, and the second - to extract all needed data.
https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=Frank's GMC, 325 ORIENT WAY, LYNDHURST, NJ, 07071&inputtype=textquery&key=[YOUR KEY]
there you need to put shop name and address separated by comma in to input param
https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJ_8hLBQVWwokRY1uywGWl8vs&key=[YOUR KEY]
this you need to use the place id from response on first request.
I just discovered the Geocoder gem and my question is related to how to test it's use through Rspec.
As I have seen here How to test geocoder gem
I created a google_data.json to simulate the googlemaps response in order to no hit their API everytime and to not consume my daily request amount (moreover in this way test are really faster). My problem comes when I want to test a function like this one
def self.find_by_radius_from_location(location, radius=10)
coords = Geocoder.coordinates(location)
Garage.near(coords, radius, units: :km)
end
and here is my test (which works if I connect to gmaps api)
describe 'find_by_radius_from_location' do
let!(:garage_inside_radius) { FactoryGirl.create(:turin_garage) }
let!(:garage_outside_radius) { FactoryGirl.create(:rome_garage) }
context 'given a city' do
it 'should return one garage' do
garages = Garage.find_by_radius_from_location('Torino', 10)
garages.first.should eq(garage_inside_radius)
raise garages.inspect
ids = garages.collect { |g| g[:id] }
ids.count.should be(1)
end
end
end
The garages coord are right (the test pass if I connect to gmaps) what is wrong is my json, because I receive 2 garages instead of 1.
Here it is
{
"status": "OK",
"results": [ {
"types": [ "street_address" ],
"formatted_address": "Via Monginevro 162, Torino, Italy",
"address_components": [ {
"long_name": "Via Monginevro 162",
"short_name": "Via Monginevro 162",
"types": [ "route" ]
}, {
"long_name": "Torino",
"short_name": "Torino",
"types": [ "city", "political" ]
}, {
"long_name": "Italy",
"short_name": "IT",
"types": [ "country", "political" ]
} ],
"geometry": {
"location": {
"lat": 45.0647,
"lng": 7.63015
}
}
}, {
"types": [ "street_address" ],
"formatted_address": "Via G. Ferraris 2/4, Roma, Italy",
"address_components": [ {
"long_name": "Via G. Ferraris 2/4",
"short_name": "Via G. Ferraris 2/4",
"types": [ "route" ]
}, {
"long_name": "Roma",
"short_name": "Roma",
"types": [ "city", "political" ]
}, {
"long_name": "Italy",
"short_name": "IT",
"types": [ "country", "political" ]
} ],
"geometry": {
"location": {
"lat": 41.8084,
"lng": 12.3015
}
}
} ]
}
What's wrong with that? Is there any way to test my find_by_radius_from_location function ? I suppose I should receive only one Garage but I receive 2... Why?
EDIT
I have found a workaround but maybe there is a better way to achieve this.
let!(:garage_inside_radius) { FactoryGirl.create(:turin_garage) }
let!(:garage_outside_radius) { FactoryGirl.create(:rome_garage) }
let(:outside_coords) { { latitude: 41.8084, longitude: 12.3015 } }
before(:each) do
garage_outside_radius.update_attributes(outside_coords)
end
I wanted to create app that will longitude, latitude by zip and name of object (for example mcdonalds). I tried to do that via google maps geocoder but my idea was wrong because geocoder returned weird results. Maybe someone know a service or strategy of getting location by zip/name please let me know.
You can test out the Google Geocoder by using the same search string in the maps.google.com search box. For example "McDonalds 2000 Australia", returns appropriate geocoding results. Are you including the country? That might clarify the search results.
reverse-geocoding from your tags means geolocation with given latitude and longitude.
If you want to geocode something you should just use Google Maps Geocode API.
http://maps.google.com/maps/api/geocode/json?address=Sydney&sensor=false
In result you have:
{
"status": "OK",
"results": [ {
"types": [ "locality", "political" ],
"formatted_address": "Sydney Nowa Południowa Walia, Australia",
"address_components": [ {
"long_name": "Sydney",
"short_name": "Sydney",
"types": [ "locality", "political" ]
}, {
"long_name": "Nowa Południowa Walia",
"short_name": "NSW",
"types": [ "administrative_area_level_1", "political" ]
}, {
"long_name": "Australia",
"short_name": "AU",
"types": [ "country", "political" ]
} ],
"geometry": {
"location": {
"lat": -33.8671390,
"lng": 151.2071140
},
"location_type": "APPROXIMATE",
"viewport": {
"southwest": {
"lat": -33.8764033,
"lng": 151.1911066
},
"northeast": {
"lat": -33.8578737,
"lng": 151.2231214
}
},
"bounds": {
"southwest": {
"lat": -33.8797030,
"lng": 151.1970330
},
"northeast": {
"lat": -33.8559920,
"lng": 151.2229770
}
}
}
} ]
}
In results array you have result objects. Coordinates are just in geometry->location.
Nothing simplier.
Here is reference: http://code.google.com/intl/pl-PL/apis/maps/documentation/geocoding/#GeocodingRequests