Getting places nearby for a city city and not for a specific latlng - google-maps

Is there a way to get all the towns around a specific city (radius of 10km) without using a single pair of latlng?
I'd like to get all the towns around the city polygon in this radius (let's say there's a town in 8 km on the north, I can't just take the city center latlng and use it as it further than 10 km from this point).
How would you do it?
Thanks,
J.
I tried to use plcae_id instead of latlng but it id not work.

with the google map API try this: (10km distance)
https://maps.googleapis.com/maps/api/place/autocomplete/json?input=**CITY_NAME**&radius=10000&types=(cities)&key=YOUR_API_KEY
You can take a look at this repository: https://github.com/drolbr/Overpass-API
(edit) example request with a python script:
import requests
api_key = "API_KEY"
query = "[out:json];area[name='Istanbul'][admin_level=2]->.a;(node[place=town](area.a);way[place=town](area.a);relation[place=town](area.a));out body;>;out skel qt;"
response = requests.get(
"https://api.openstreetmap.org/api/interpreter",
params={
"data": query,
"key": api_key
}
)
data = response.json()

Using the Places API, you can request a nearby search of x radius from a center latitude/longitude literal up to 50,000 meters.
For example, using JavaScript, we fetch the nearby search API and use (cities) as the type parameter to use the collection of cities including towns, etc. See https://developers.google.com/maps/documentation/places/web-service/supported_types for all the supported types.
GET https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=API_KEY&location=-33.8670522%2C151.1957362&radius=8000&type=(cities)
const API_KEY = "API_KEY";
async function getNearbySearch(center, radius, type) {
try {
const response = await fetch(`https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=${API_KEY}&location=${center.latitude}%2C${center.longitude}&radius=${radius}&type=${type}`);
const result = await response.json();
return result;
}
catch(error) {
console.error(error);
return null;
}
};
getNearbySearch({ latitude: -33.8670522, longitude: 151.1957362 }, 8000, "(cities)").then((nearbyCities) => {
console.log(nearbyCities);
});
The response would look like: https://developers.google.com/maps/documentation/places/web-service/search-nearby#nearby-search-responses
Because of a bug with the (cities) type collection, we can instead query locality and administrative_area_level_3 to combine the cities manually instead.
const API_KEY = "API_KEY";
async function getNearbySearch(center, radius, type) {
try {
const response = await fetch(`https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=${API_KEY}&location=${center.latitude}%2C${center.longitude}&radius=${radius}&type=${type}`);
const result = await response.json();
return result;
}
catch(error) {
console.error(error);
return null;
}
};
async function getNearbyCityCollectionSearch(center, radius) {
const localityList = await getNearbySearch(center, radius, "locality");
const administrativeAreaLevel3List = await getNearbySearch(center, radius, "administrative_area_level_3");
return localityList.results.concat(administrativeAreaLevel3List.results);
};
getNearbyCityCollectionSearch({ latitude: -33.8670522, longitude: 151.1957362 }, 8000).then((nearbyCities) => {
console.log(nearbyCities);
});
See this for the Places API documentation: https://developers.google.com/maps/documentation/places/web-service/search-nearby

Related

Override Chrome Storage API

I would like to override chrome.storage.local.set in order to log the value of a storage key when the Chrome Storage API is called:
var storage_local_set = chrome.storage.local.set;
chrome.storage.local.set = function(key, value) {
console.log(key);
storage_local_set(key);
}
But I get Illegal invocation: Function must be called on an object of type StorageArea when storage_local_set(key) gets called. How can I store the data after logging the key?
For chrome.storage.sync.set this is what I tried based on the solution given:
const api = chrome.storage.sync;
const { set } = api;
api.set = function (data, callback) {
console.log(data);
set.apply(api, arguments);
};
But this is not hooking the API
You need to use .call() or .apply() to provide this object:
storage_local_set.apply(this, arguments);
The parameters in your override don't match the documentation though. If you want to match the documentation then do it like this:
const api = chrome.storage.local;
const { set } = api;
api.set = function (data, callback) {
console.log(data);
set.apply(api, arguments);
};
And if you want to change the signature to separate key and value:
const api = chrome.storage.local;
const { set } = api;
api.set = (key, value, callback) => {
console.log(key, value);
set.call(api, {[key]: value}, callback);
};

Display one value pair from JSON object

I'll preface this saying I'm a UX Designer that's new to React.
I'm using Expo/React-Native and using the "Location" feature to get the device's location information. I'm able to get the information back in a JSON object by using:
const { height, width } = Dimensions.get("window");
class Explore extends Component {
static navigationOptions = {
header: null
};
state = {
locationResult: ""
};
componentDidMount() {
this._getLocationAsync();
}
_getLocationAsync = async () => {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== "granted") {
this.setState({
locationResult: "Permission to access location was denied"
});
}
let location = await Location.getCurrentPositionAsync({});
let geocode = await Location.reverseGeocodeAsync(location.coords);
this.setState({ locationResult: JSON.stringify(geocode) });
};
And in my render I'm calling the value using:
<WelcomeText>
Discover {this.state.locationResult}
</WelcomeText>
Which returns the object:
[{"street":"Stockton St","city":"San Francisco","region":"CA","country":"United States","postalCode":"94108","isoCountryCode":"US","name":"1 Stockton St"}]
But how do I go about just displaying the value of "City" that's in the object?
Try this:
<WelcomeText>
Discover {this.state.locationResult[0].city}
</WelcomeText>
Explanation:
Your this.state.locationResult is an array of objects. With this.state.locationResult[0] we are accessing the first object. Then we can use the . operator to access the property we want. In your case .city
Edit:
You need to pass in geocode without stringifying it, otherwise you cannot access it like i described it above. reverseGeocodeAsync is already returning an array of objects, no need to transform it to a string.
Replace:
this.setState({ locationResult: JSON.stringify(geocode) });
with:
this.setState({ locationResult: geocode });
Edit2:
Here is a working example: https://snack.expo.io/B1SqSd3iN

how to get a geocode api address pattern .fromaddress?

Im using geocode api from google maps and Im trying to use the answer from server to fill up a form, the problem is, it's not a pattern of object, the result[0].address_components sometimes return 4, 5 and 7 obj and I can`t to know with one is the city, country etc, there is some way to get like result.something.street, result.something.city etc?
else{
Geocode.fromAddress(cep).then(
response => {
const { lat, lng } = response.results[0].geometry.location;
console.log(response.results[0].address_components);
console.log(response);
},
error => {
console.error(error);
}
);
}
You need to filter the object
Working Fiddle
function getValue(adress_components, component_name) {
return adress_components.filter(c => c.types[0] == component_name)[0].long_name
}
var components = response.results[0].address_components;
console.log(getValue(components, 'street_number'));
console.log(getValue(components, 'locality'));
console.log(getValue(components, 'country'));
console.log(getValue(components, 'postal_code'));

Angular2 build getlocation from googlemaps Service

I want to create a service where i can get my current location.
I want to put this in a service so that i can use this location in several Components.
The issue is that when i try this my component tries te get the lat and lon before google maps finishes the ajax call.
Does somebody has a solution for this issue?
setCurrentPosition() {
if ("geolocation" in navigator) {
navigator.geolocation.getCurrentPosition((position) => {
this.latitude = position.coords.latitude;
this.longitude = position.coords.longitude;
this.zoom = 12;
return this.latitude, this.longitude ;
});
}
}
This is how i get my location in the service.
My components want to use the latitude and longitude to soon because the ajax call hasn`t jet retrieved the informatio. How can i fix this?
Have you used promises before you can even use a promise for this. The promise will resolve when the api gets lat and lng. You can call api like
this.setCurrentPosition().then((response)=>{
this.lat = response.latitude;
this.lng = response.longitude;
});
setCurrentPosition() {
return new Promise((resolve, reject) => {
if ("geolocation" in navigator) {
navigator.geolocation.getCurrentPosition((position) => {
let res = {
latitude: position.coords.latitude,
longitude:position.coords.latitude
}
resolve(res);
});
}
});
}
Write your function as an observable amd subscribe to it from your component so it will get value once the latitude and longitude are returned by this service . Refer https://angular-2-training-book.rangle.io/handout/observables/using_observables.html

Using callbacks in a non-async-context

I have a service with a method called "getGmapsDistance()". Here im using the google maps api to get the distance between an origin an an destination.
export default Ember.Service.extend({
getShortestDistanceInMeters: function(location) {
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix({
...
}, this.callback); //<<<<<< !!!
},
callback: function(response, status) {
....
}
});
In my controller if got a array with locations and now I want to iterate over it and want check each element if the distance is <= the max destination.
locationsNearby: Ember.computed('locations', function() {
//...
var filteredResult = [];
locations.forEach(function(locat) {
if (this.get('distanceService').getShortestDistanceInMeters(locat) <= maxDistance) {
filteredResult.pushObject(locat);
}
});
return filteredResult;
})
Unfortunately the GMaps API for distance calculation uses a callback so the request is async.
How can I solve that problem?
You can not make an async call synchronous! This is an javascript language limitation and is important to understand! Javascript has only one thread, so this can't be changed by a library or so!
The fancy new way to handle callbacks are Promises.
You really really should checkout the specifications!
It's one of the most beautiful specifications you will ever read!
Ember uses Promises heavily! For example a routes model hook waits for a Promise to resolve before going on with the transition.
In your case you want to update the computed property when the promise resolves. Because ember-data causes this to happen often they provide two fancy classes: PromiseObject and PromiseArray. A computed property depending on a computed property that returns a PromiseObject/Array will recompute when the promise resolves:
locationsNearby: Ember.computed('locations', {
get() {
let promise = Ember.RSVP.all(this.get('locations').map(location => Ember.RSVP.hash(({
location,
distance: this.get('distanceService').getShortestDistanceInMeters(location)
})))).then(hashs => hashs.filter(hash => hash.distance <= maxDistance).map(hash => hash.location));
return DS.PromiseArray.create({promise});
}
})
To explain it a little:
I build an array with hash's of the location and a promise to the distance:
let locationsWithDistancePromise = this.get('locations').map(location => {
distance: this.get('distanceService').getShortestDistanceInMeters(location),
location
})
Then I use RSVP.hash on all of them to get an array of promises that will resolve to an array of hashes with distance and location:
let hashPromiseArr = locationsWithDistancePromise.map(h => Ember.RSVP.hash(h));
Now I use Ember.RSVP.all to get an promise that will resolve to an array of hashes with location and distance:
let hashArrPromise = Ember.RSVP.all(hashPromiseArr);
An finally I .then on the promise and filter the nearby locations. Also I map the hash to a array of locations.
let promise = hashArrPromise.then(hashs => {
return hashs.filter(hash => hash.distance <= maxDistance)
.map(hash => hash.location);
});
And wrap it as an PromiseArray
return DS.PromiseArray.create({promise});
You can just loop over this Computed Property from handlebars with {{#each}} or use it in another Computed Property:
allNearbyLocations: Ember.computed('locationsNearby.[]', {
get() {
return this.get('locationsNearby').toArray().join(' - ');
}
}
Of course you need to rewrite getShortestDistanceInMeters so that it returns a Promise:
getShortestDistanceInMeters(location) {
var service = new google.maps.DistanceMatrixService();
return new Ember.RSVP.Promise((resolve, reject) => {
service.getDistanceMatrix({
//...
}, (response, status) => {
if(status.error) {
reject(response);
} else {
resolve(response);
}
});
});
}