I'd like to implement a way to display a list of stored addresses sorted by proximity to a given address.
Addresses in the list will be stored in a database table. Separate parts have separate fields (we have fields for postal code, city name, etc.) so it is not just a giant varchar. These are user-entered and due to the nature of the system may not always be complete (some may be missing postal code and others may have little more than city and state).
Though this is for an intranet application I have no problems using outside resources including accessing internet web services and such. I'd actually prefer that over rolling my own unless it would be trivial to do myself. If Google or Yahoo! already provides a free service, I'm more than willing to check it out. The keyword is it must be free, as I'm not at liberty to introduce any additional cost onto this project for this feature as it is already a bonus "perk" so to speak.
I'm thinking of this much like many brick & mortar shops do their "Find a Location" feature. Showing it in a simple table sorted appropriately and displaying distance (in, say, miles) is great. Showing a map mash-up is even cooler, but I can definitely live with just getting the distance back and me handling all of the subsequent display and sorting.
The problem with simple distance algorithms is the nature of the data. Since all or part of the address can be undefined, I don't have anything convenient like lat/long coords. Also, even if I make postal codes required, 90% of the addresses will probably have the same five postal codes.
While it need not be blisteringly fast, anything that takes more than seven seconds to show up on the page due to latency might be too long for the average user to wait, as we know. If such a hypothetical service supports sending a batch of addresses at once instead of querying one at a time, that'd be great. Still, I should not think the list of addresses would exceed 50 total, if that many.
Google and Yahoo! both provide geocoding services for free. You can calculate distance using the Haversine formula (implemented in .NET or SQL). Both services will let you do partial searches (zip code only, city only) and will let you know what the precision of their results are (so that you can exclude locations without meaningful information, though Yahoo! provides more precision info than Google).
The Google Maps API is no good to you due to their terms of use. However, Yahoo offer a REST service for turning addresses into Long/Lat coordinates, which you could then use to calculate distances. Its here.
Require them to enter a ZIP code, then create a database table mapping ZIP code to latitude/longitude pairs (or find one online). I don't know how it is where you work but over here, ZIP code can be specific to several meters, so that should be precise enough. Then use this method to calculate the distance between two ZIP codes:
public static double distance(double lat1, double lon1, double lat2, double lon2, char unit)
{
double theta = lon1 - lon2;
double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) +
Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
dist = Math.Acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
if (unit == 'K')
{
dist = dist * 1.609344;
}
else if (unit == 'N')
{
dist = dist * 0.8684;
}
return (dist);
}
private static double deg2rad(double deg)
{
return (deg * Math.PI / 180.0);
}
private static double rad2deg(double rad)
{
return (rad / Math.PI * 180.0);
}
The advantage of using your own code over a geocoding service is that you can then do a bunch more interesting calculations against the data as well as storing stuff alongside it in your db.
Can't you just use google maps API to get the distances and sort them on your side?
http://code.google.com/apis/maps/
I'd suggest investigating the google maps API.
It would require you to have an external connection (and for it to be alright to shunt the data over it to a web service) but it provides what you require, namely the distance by asking for a route between 2 points and getting the distance from it.
API reference of the directions API
One thing we've done at my company is to cheat and use the latitude/longitude of the zip code (Roughly the center of the zip code area). It's not perfect, but it's close enough for those find me x within n miles of y types of searches. This is especially helpful when the addresses can't be recognized by address cleaning services.
At some point I came across a free zip code to latitude/longitude lookup table to use in this approximation. I'm sorry I don't have the link to this any more.
Check out this website: http://geocoder.us/help/utility.shtml
You can process records, 1 per 15 seconds like this:
http://geocoder.us/service/distance?zip1=95472&zip2=94305
They also have a subscription service without the time limit
Someone else has done it already at Daft Logic (edit: typo). They use Google Maps API with the Great-circle formula. I don't think it's hard to implement.
Update: Practically, you only need to get the coordinates from your favourite provider, then do the calculation with your code. You can preload the shops' coordinates, when users provide their location - you can even use this for validation. Then, when the request is made, you can only lookup the customer's location.
Related
I am building an app that will require extensive use of the autocomplete function and have currently implemented under Nearby Search. I recently learned however that this is the priciest option given its high cost + associated Contact and Atmospheric data imposed costs.
I am therefore looking for a good option to get relevant autocomplete search results based on the users location without the need for 'Nearby search'. I care about the UX and thus want to avoid people scrolling too much to find a place near them. The only field I need is name & potentially address.
I tried Nearby search, if I understand correctly this is the only way to get autocomplete predictions based on where you physically are located - I have now learned that this is too expensive however
Autocomplete and Nearby Search are entirely different operations and APIs, you can combine both to build a user-friendly experience but they each play a very different role.
Place Autocomplete provide predictions of places based on the user's input, i.e. characters the enter into an input field. These predictions can be biased, even restricted, to a small area around the user's location, to increase the chances that they will represent places near to the user. Depending on whether places far away from the user are acceptable or useful, or not, you can use one or the other:
locationbias if predictions far away are acceptable and useful, e.g. a user searching for a place that is not necessaraly where they are, or in situations where the user location is either not available or not very precise, e.g.
user wants to find a place to go to
user location is obtained from geolocating their IP address
user location is obtained from geolocating their cell towers
locationrestriction if only very nearby predictions are acceptable and user location is known to be very precise (e.g. GPS or other high-precision sources). This would make sense in mobile applications when the user location is provided (by the phone's OS) with a small radius (e.g. under 100 m.) and the user really just wants to find places that describe where they are now. Even then, beware that some places can be bigger than you'd expect, e.g. airports include runways.
Note on billing: Place Autocomplete can be free under specific conditions: when your application implements session tokens and there is a Place Details request at the end of the session, in which case Place Details is billed and Autocomplete is not. However, even if your application implements session tokens, each time a user doesn't pick a prediction, Autocomplete is billed as a session without Details. And in the simpler case, if your application does not implement session tokens, all Autocomplete is billed as per-request (and Place Details is billed separately, on top of that).
Nearby Search can provide nearby places (and can rankby=distance) based on only the user's location and without user's input. This can be used to show an initial list of places (e.g. the nearest 5 places) even before the user starts typing. There a few caveats:
results depends heavily on the user location being very precise
results will only include establishment places, i.e. business, parks, transit stations
If you'd want addresses instead of businesses, you could use reverse geocoding instead of Nearby Search, with the caveat that this can return results that are near/ish and don't necessarily represent the exact place where the user is at. This is more useful when you want to find addresses around a location; they may include the actual address of that location, but that is not guaranted.
I am currently working on an Agent based model in Anylogic which consists of multiple stores with a driver assigned to each store and Customers who place orders and these orders are then delivered to them from the nearest store.
I have created an agent type "Customer" with a certain order frequency event. I know that anylogic allows to assign a GIS location for the agent by placing a node on the GIS map, searching the name of the location on the map or by defining the location programmatically (setLocation(INodenode),setLocation(Point point),setLocation(Agent agent)&setLatLon (double latitude, double longitude)).
However, I want to assign a random GIS location "GIS node" to the customer each time an order is generated.I want to know If there is a certain function that I can use to do that or any other way.
Any help is highly appreciated.
You can use this code in: Agent actions, On Startup:
Point pt = get_Main().region.randomPointInside();
setXYZ( pt.x, pt.y, pt.z );
If you get "region" cannot be resolved, you should check in the Main tree, presentation, map, if the "region" name is not there that means that you have not made it yet. You can go to the Pallet, Space Markup and use GIS Region to draw the region you want.
I don't think you want a random location in the whole world since you don't have customers in the middle of the pacific ocean, the top of mount Everest, the white house or some point in the Antarctic.
So what you really want to do, is to define a GIS region, which is one of the elements that you can find in the same place you find a GIS point, with that you can select on the map the region in which your customers can exist and then you can just select a random point:
region.randomPointInside()
Remember though, that the route to each random point has to be calculated, so this can be quite slow if you have too many random points and deliveries to those points since the route is calculated every time...
Is it possible to get all postal codes in a given location inside the given radius?
What Google API should I use?
Example: I have a lat. and a long. and my radius is 15kms. How do I get the post codes of the areas inside the radius?
I'm kinda new to using API's and Google API's.
Thanks!
This is a process called "Reverse Geocoding" Google offers it here - https://developers.google.com/maps/documentation/javascript/examples/geocoding-reverse
However pretty sure that Google's API will try to give you one closest result rather than many.
You can do this with APIs (often paid for) however, be warned that you have to be quite careful with the radius element, setting it too small in rural areas will bring back 0 results and setting it too big in urban areas will bring back potentially thousands.
Closed. This question is not about programming or software development. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed last month.
Improve this question
I am exploring the Google APIs, mostly the Places API. Because the number of requests to the Google Places API is limited to 100,000, I am looking for ways to minimize the number of requests sent to the API. I was thinking of using a database to store previously received responses, so in the future I could retrieve them without making requests to the API and will do request to the API only in a case if the needed data had not been previously stored in my database.
According to Google API terms of use, specifically the section 10.1.3 Restrictions against Copying or Data Export, it is not allowed to store data indefinitely, but it is legal to cache it temporarily:
You must not pre-fetch, cache, or store any Content, except that you may store: (i) limited amounts of Content for the purpose of improving the performance of your Maps API Implementation if you do so temporarily (and in no event for more than 30 calendar days), securely, and in a manner that does not permit use of the Content outside of the Service; and (ii) any content identifier or key that the Maps APIs Documentation specifically permits you to store. For example, you must not use the Content to create an independent database of "places" or other local listings information.
I find this section not well explained. Can I store any data received by the API in my database for 30 days or only ids of places? Because in some other contexts I have read that it is only allowed to store the ids. I understood it this way: I can store places ids indefinitely, but can use the whole data only for 30 days.
Because I have been reading about Google APIs for only a couple of days, I have maybe missed some term of use, so I would be really thankful if you could help me.
Any suggestions how to minimize the number of calls to the APIs, or sharing some experiences related to real projects using those APIs will be really appreciated. Also if you could suggest me some alternative APIs which could provide similar functionality would be really helpful.
Thank You in advance!
From my experience with the Google Places API, your understanding is just about correct. Let me explain the two stipulations in my own words:
i) Without prefetching, or redistributing outside your application, you may cache API results for up to 30 days.
ii) You can use a place ID or key in your application specific data, but nothing else (e.g. if your app lets user's "check-in" places, you can store a list of place IDs where they've been on a user object and lookup the places as needed by ID, but you can't store a list of all the places with Google's names/details).
In order to reduce the number of API calls and accelerate my app, what I do is cache the nearby place calls in a simple key-value cache, where the key is the lat-lng pair rounded to a certain precision (so that calls within a certain radius will hit the cache) and the value is the entire JSON result string. Here is my code, which is Java running on Google's App Engine:
// Using 4 decimal places for rounding represents approximately 11 meters of precision
// http://gis.stackexchange.com/questions/8650/how-to-measure-the-accuracy-of-latitude-and-longitude
public static final int LAT_LONG_CACHE_PRECISION = 4;
public static final int CACHE_DURATION_SEC = 24 * 60 * 60; // one day in seconds
...
String cacheKey = "lat,lng:" + round(latitude) + "," + round(longitude);
asyncCache.put(cacheKey, dataJSON, Expiration.byDeltaSeconds(CACHE_DURATION_SEC), MemcacheService.SetPolicy.SET_ALWAYS);
...
private static double round(double value) {
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(LAT_LONG_CACHE_PRECISION, RoundingMode.HALF_UP);
return bd.doubleValue();
}
As for alternative APIs, I would suggest you look at the following:
Yelp API - provides bar/restaurant data that Google lacks
Facebook API - easy to use if you're already using Facebook's SDK
Factual: Places Crosswalk - aggregates and normalizes places data from many sources, including Facebook and Yelp, but not Google
Currently I'm only using Google Places API, but I'm planning on adding Yelp or Factual later to improve the results for the end user.
I'm in the concept development stage of an iOS app that is essentially a game. One of the things I want to do is to get information about the current location. I've not used the map kit so far, and after a quick read through various documentation, it looks like it is designed mainly as a display kit. What I'd like to do in addition to displaying a map is to query data that might be at the location. For example, if I provide latitude and longitude, I want to know whether that location represents land or water. If it's on land, how close is it to the nearest street? If it's not near a street, what other information might there be about the spot?
I realize there are vast amounts of data available that are geocoded, but is there any information that can be queried directly from the map kit? I would have thought things like elevation would be easily available, but I haven't seen anything like that yet. Am I just looking in the wrong place?
As far as I am aware there is no data that you can query directly from MapKit - i.e. you cannot ask MapKit if a location is on land or water.
You could use reverse geo-coding with the current longitude/latitude to find out details about the location, for example nearest street/town, or which country the location is in.
Check out the built in Apple Geocoding framework, or the Google Geocoding API
Hope this helps.