iOS MKDirections for multiple destinations and a single source - ios

My application needs to get the "closest" walking point to the user from a set of 10. I have seen that MKDirections does this with "calculateDirectionsWithCompletionHandler" for a single source, destination locations. My question is, do I have do make 10 requests and then check which one is the closest one in distance or there is a way of sending multiple destinations and the response would be the closest one walking?
Thank you

As far as I'm aware there is no way to specify more than two points for an MKDirections request. Your proposed solution of creating 10 separate requests should work in theory, though keep in mind that:
MKDirections does not calculate directions locally on the device, but reaches out to a remote API which calculates them and returns the response. If you're calculating 10 routes, there will likely be a noticeable delay for the user while waiting for all the results to be returned.
Because directions are calculated using a remote API, Apple likely would frown on something like this- if you're hitting their directions API too frequently they might throttle you, or they may just reject the app when it's submitted to the App Store if they see that this is happening.
I'm not sure of your exact requirements, but depending on the accuracy you need, one solution could be to calculate the distance between the start point and each end point using the haversine formula, which would give you the distance between the two points as-the-crow-flies. Because you're calculating walking directions (as opposed to driving, where you're limited to following specific roads and subject to traffic), the closest distance from these calculations will likely be the closest in terms of actual walking distance/time, at which point you could then make a single MKDirections request for those details.

// try this annotation.coordinate is the locations and ULManager.location //as the user location
let dirRe = MKDirectionsRequest()
dirRe.source = MKMapItem(placemark: MKPlacemark(coordinate: (self.ULManager.location?.coordinate)!, addressDictionary: nil))
dirRe.destination = MKMapItem(placemark: MKPlacemark(coordinate: (annotation.coordinate), addressDictionary: nil))
dirRe.transportType = .Walking
let requestAll = MKDirections(request: dirRe)
requestAll.calculateDirectionsWithCompletionHandler ({
(response: MKDirectionsResponse?, error: NSError?) in
// do your staff here
})

Related

How to evaluate the remoteness of a location given its coordinates?

I need to be able to evaluate how remote a location is given its geographical coordinates. I rate remoteness based off of a few key metrics, so far, I am only able to calculate a subset of all the required metrics:
The cellular reception at the given coordinate. More specifically, the density of cell towers around the coordinate. This can be found using opencellid.org.
Elevation. This can be found using Google's Elevation API
How can one find these remaining metrics for remoteness?
The type of natural feature the coordinate is in. (eg. Lake, River, Glacier, Ocean, Island, Mountain)
Distance to the nearest road. (Google's Snap Road API and Nearest Road API only work if the coordinate is within 50m of a road, that will not work as some coordinates are hundreds of km from the nearest road).
About land type
For your first question it has already been answered here, except it is only for land/water.
My approach would be the following:
Using maps static, you get the image at your coordinate, you get the pixel at the center of your image (your coordinates) and you use a hashmap/dictionary that contains all the different possible colors and their land type, would be very quick to implement. But you can find out different ideas by reading the first link provided.
For strength of cellular signal
As for your second question, you can use Google API to detect the closest cell towers object, using the locationAreaCode that you can obtain through the coordinates:
An example cell tower object is below.
{
"cellTowers": [
{
"cellId": 170402199,
"locationAreaCode": 35632,
"mobileCountryCode": 310,
"mobileNetworkCode": 410,
"age": 0,
"signalStrength": -60,
"timingAdvance": 15
}
]
}
What is the purpose I wonder? You could take a sampling of coordinates around the fix and if they are mostly on a hill or in water it is definitive, it seems people know how to figure out this kind of stuff with google apis.
Would this be good enough?
Get Lat/Lon and range from a sources like this: https://my.opencellid.org/dashboard/login?ref=opencellid for free. Use a formula to determine the distance between the gps locations like this: https://nathanrooy.github.io/posts/2016-09-07/haversine-with-python/. Then make your own determination on strength based on "range" and terrain. perhaps create a DB table of say 500 zip codes with label for terrain type rating. If 10 or something it's the worst terrain and you drop the strength by something that makes sense.

Finding the distance between current location and another location (Swift 5)

I'm not a programmer but have been playing around with a side project for fun. I'm using Xcode 10, Swift 5. I've pieced together a handful of things through youtube and SO but I've searched and experimented with this for three days and I'm running into dead ends here.
I am trying to determine the distance between a user's current location and a preset point (in this case the airport). I am able to find the distance between two hard-coded locations. I am also able to find and print the user's current location in the console. But when I try to combine those I am struggling, most often getting the error
'Value of type 'CLLocationCoordinate2D' has no member 'distance''
The code that working is and gives me the distance in meters I would like is:
lazy var phx = CLLocation(latitude: 33.409016, longitude: -111.805576)
lazy var distanceFromPhoenixToVegas = las.distance(from: phx)
And this will print out the current location coordinates:
func printCoordinates(){
if let location = locationManager.location?.coordinate {
print (location)
}
}
If any one could offer guidance I would appreciate it.
Side note, there are a lot of similar questions on Stack Overflow. There are questions about getting a user's current location, and questions about getting distances between two points. I believe this is essentially what I am asking, but it was only answered by the original poster, and the answer seems not exactly correct to me. iOS & Swift: display distance from current location?
coordinate is of type CLLocationCoordinate2D You only need locationManager.location
if let location = locationManager.location {
print(phx.distance(from: location))
}

Wrong distance using distanceFromLocation:

I'm trying to find out what's wrong but it seems like the mentioned method is just returning wrong values. I'm setting coordinates in simulator, then just print them and calculate distance:
(lldb) p location.coordinate
(CLLocationCoordinate2D) $1 = (latitude = 51, longitude = 0.10000000000000001)
(lldb) p _oldLocation.coordinate
(CLLocationCoordinate2D) $2 = (latitude = 51, longitude = 0)
Now I'm calculating distance:
distance = (CGFloat)[location distanceFromLocation:_trackEndLocation];
And when I print it i get:
(lldb) po self.trackDistance
7019.76758
Now, the problem is that users tell me that app returns too big distance. As I wanted to debug it, I've checked the distance at page to calculate distance between two points.
The results are as following:
As you can notice, the distance according to the webpage is 6.997km while Apple method tells me 7.019km. I wonder who is incorrect, Apple or the webpage and what to do with this matter. The difference isn't big, but when you accumulate it between few points it can be disturbing.
The Apple doc page for distanceFromLocation says this:
This method measures the distance between the two locations by tracing a line between them that follows the curvature of the Earth. The resulting arc is a smooth curve and does not take into account specific altitude changes between the two locations.
I suspect Google Maps does consider the terrain between the two points, and that's why you saw a 0.3% difference in your test. However, I doubt your customers are complaining about that level of error. It's more likely the error is from a different cause.
Without knowing more about your algorithm it's hard to say, but if you're tracking distance traveled, the error might be caused by jitter in the phone's GPS coordinates. (That would cause a straight line path to look like a zigzag, which would yield a longer distance.) You could record some real data from your app to see for sure.
The problem was that I was checking the accuracy and filtered some results out if the accuracy was bad. That's why sometimes the distance was wrong. I've fixed the accuracy filtration and everything is working fine.

Get location data when out of service

I'm working on a iPhone app that stores location data from a user. However, sometime the user doesn't have service.
Is there an API that estimates location data when the phone gets back into service? Or any other suggestions
No, there is no such API, because that would create wrong locations.
You have to write yourself such a method, that hopefully works in the scope of your application demands:
E.g You could do a linear interpolation when the GPS service has an outage for some seconds.
e.g:
A liner interpolation of lat and lon values work without special geographic calculations.
Just it would not work if you cross the datum limit (border longitude = 180E to 180 W),
and maybe not if you cross the poles.
But both situations will practically not happen.

Order of CLLocation objects in -distanceFromLocation:

This is my first time posting a question here, but I have found a lot of help from other people's questions.
My question refers to the -distanceFromLocation: function in CLLocation. I had assumed that finding the distance between point A and point B would be the same as that between point B and point A, but I have found that it is not. I have tested this in a very simple case:
CLLocation *test1 = [[CLLocation alloc] initWithLatitude:37.529530 longitude:-122.259232];
CLLocation *test2 = [[CLLocation alloc] initWithLatitude:47.900002 longitude:-103.495102];
NSLog(#"%f vs %f",[test2 distanceFromLocation:test1],[test1 distanceFromLocation:test2]);
[test1 release];
[test2 release];
The output to this was 1907269.942754 vs 1908105.959114, a difference of almost 900 meters.
Though 900 meters may be a small percentage, I am trying to determine if the user is closer to something than an annotation and 900 meters can change that.
My question is, which one of these values, if any, is correct? Also if which location I test against is important, do I need to always test against the same location (e.g. user to destination and annotation to destination rather than destination to user and annotation to destination)?
Sorry that the sample is a bit out of context, as my project is rather large and this illustrates my problem. Any help would be appreciated as this has caused me quite a bit of confusion and frustration.
The error you're observing is 1 part in 2000. Presumably the algorithm used in this method is optimized for speed, so sorting a list of locations on distance is fast, rather than accurate to the millimeter.
If you need accurate results, don't use these methods but find another way. If you need reproducible results, order the arguments in a defined way, e.g. always start with the lower latitude.

Resources