Calculate proper latitudeDelta and longitudeDelta based on radius? - swift

Does anyone know of a mathematical way to calculate the proper latitudeDelta/longitude delta of a MapView region based on search radius? For instance, I give my users the option to search for items within a radius of 5, 10, 25, 50 & 100 miles. I would like the MapView region to accurately reflect that search radius and just show enough "map" to encompass the search radius.

Forget about the latitude and longitude. Just convert from miles to meters and then create an MKCoordinateRegion by calling init(center:latitudinalMeters:longitudinalMeters:), where the latitudinalMeters and longitudinalMeters are twice the radius, and use that, centered at the user's location, to set the map view's region.

Related

NSPredicate to limit latitude longitude range according to MapView bounds

So I have an app with a MapView and I use CoreData to load annotations associated with locations nearby the center of the map. Currently, I define the lat/long range statically like this:
var fetchDataPredicates = [NSPredicate]()
fetchDataPredicates.append(NSPredicate(format: "itemLatitude BETWEEN {%f,%f} AND itemLongitude BETWEEN {%f,%f}", (latitude-0.10), (latitude+0.10), (longitude-0.10), (longitude+0.10)))
However, this is a pretty poor solution. If the user has zoomed out far in the map then the data would only cover a small portion of it.
Does anyone have any good ideas on how to dynamically adjust the lat/long range according to the MapView bounds?
Thanks!
A likely solution would be to ask the map view for its region. That's an MKCoordinateRegion which includes
CLLocationCoordinate2D center
MKCoordinateSpan span
The span includes longitude and latitude deltas, which look like exactly what you need.

Get lat/lng center of country, state or district

Given is a DB full of parent/child relationships of political district geo data/names:
Country
State
District
Now I'm querying for that data, building a string like germany,bavaria,ebersberg and then I try to fetch the lat/lng center of that district via the Nominatim API (part of OpenStreetMaps).
Example String:
http://nominatim.openstreetmap.org/search?format=xml&polygon=0&addressdetails=0&q=germany,bavaria,ebersberg
Problem is, that I get back a bunch of POIs with lat/lng instead exact geographical data. This often results in having exact the half of that district displayed as the first POI could be close to that districts border.
Does anyone know of a way to get the lat/lng of the center or how to center a OSM map? OR does anyone know of an alternate API that can achieve this and tell how it works/make an example?
Does anyone know of a way to get the lat/lng of the center or how to center a OSM map?
When you get a bunch (list, set) of points of interest with latitudes and longitudes, you have a feature, not a problem.
You iterate through the POI, building a bounding rectangle that includes all of the POI. In other words, you find the minimum latitude, minimum longitude, maximum latitude, and maximum longitude.
You find the center of the rectangle by the formula
(maximum + minimum) / 2
The bounding area should be small enough that you're not going to incur much error working with latitude and longitude.
Otherwise, you can calculate the distance between the minimum latitude, longitude and the maximum latitude, longitude. The center is half the distance from the minimum latitude, longitude. Convert that center point back to a latitude and longitude for your answer.

MKCircle - Stroke Width equivilant to meters

I have a MKCircle. I would like to be able to set a stroke width equivilant to meters not points. So that I can draw an overlay with both radius in meters of a stroke width in meters.
I understand that the points to meters relationship changes whenever the map is zoomed. I have a very low annotation count (1) right now so removing and readding it on zoom should be OK if I can figure out a way to calculate the desired stroke width in points for a meter distance at a given map state.
The first thing to consider is whether you really want to do this: the line could wind up being invisibly thin if the user zooms out.
The only way I can see to do it is to create an appropriately-sized MKCoordinateRegion using MKCoordinateRegionMakeWithDistance and then use MKMapView's convertRegion:toRectToView: to convert it to a CGRect, from which you can read out the width/height to calculate the appropriate line width.

iPhone: Set Map zoom level on the base of distance

I want to set the zoom level of google map on the base of variable value so it show only part of map on start-up. Basically i want to show only surrounding area from user location.
For example if variable value is 30 mile, then map show only 30 mile surrounding area from current location and zoom in/out accordingly.
Create a MKCoordinateRegion using the MKCoordinateRegionMakeWithDistance function and pass it to the map view's setRegion:animated: method.
Note that MKCoordinateRegionMakeWithDistance requires meters so you'll need to convert the miles to meters first.

MKMapView Zoom and Region

I'm familiar with using Google Maps Javascript API. Recently I started using MapKit framework for an iphone project, but I'm having a hard time to figure out zooming and setting a region on map.
In Google Maps API I used to use integer zoom levels like 8, 9, 10 along with straightforward function setZoom(). The only equivalent method I can see in the MapKit framework is setRegion:animated. As I understand, I need to set a region's span's latitude and longitude "delta" values to specify zoom level. But I really don't have an idea what these values represent(I read the documentation).
When I use a MKMapView delegate and trace the span values in regionDidChange delegate method results don't seem to correlate each other. It's ok when I zoom out and see the span delta values are increasing as specified in documentation. But suddenly I drag the map without zooming and delta values become 0.0.
Can somebody please explain what is the reference point to these span and delta? Or is there any algorithm to convert an integer zoom level(like 9) to these delta values?
As a bonus question is there any way to specify a minimum-maximum zoom level on a MKMapView :)
Thanks
First of all, MKMapView does not use/have a predefined set of zoom levels like Google Maps does.
Instead, the visible area of a MKMapView is described using MKCoordinateRegion, which consists of two values:
center (the center point of the region), and
span (the size of the visible area around center).
The center point should be obvious (it's the center point of the region.)
However, span (which is a MKCoordinateSpan) consists of:
latitudeDelta (the vertical distance represented by the region), and
longitudeDelta (the horizontal distance represented by the region).
A brief example. Here's a toy MKCoordinateRegion:
center:
latitude: 0
longitude: 0
span:
latitudeDelta: 8
longitudeDelta: 6
The region could be described using its min and max coordinates as follows:
min coordinate (lower left-hand point):
latitude: -4
longitude: -3
max coordinate (upper right-hand point):
latitude: 4
longitude: 3
So, you can specify zoom levels around a center point by using an appropriately sized MKCoordinateSpan. As an approximation of Google's numeric zoom levels, you could reverse engineer the span sizes that Google uses for a given zoom level and create a span, accordingly. (Google describes their view regions in the same way that MKMapView does, as a center + span, so you can pull these values out of Google Maps.)
As for restricting the region, you may play w/ this delegate method:
mapView:regionWillChangeAnimated
e.g. by resizing the region back into your allowed zoom levels. (Kind of like how table views will let you scroll past the edge, but will then rubber band back into place.) However, your mileage may vary, since I haven't used it for this purpose.
btw, there are definite fixes/improvements in OS 3.1 to aspects of MapKit that were giving me trouble in 3.0.
If you prefer using explicit zoom levels instead of defining an MKCoordinateSpan, I wrote a category that adds support for specifying the zoom level of an MKMapView. The code can be found here.
The span is in degrees of latitude and longitude. There is a method for constructing MKCoordinateRegion structs that takes distance, instead. It may be that you are using MKCoordinateRegionMakeWithDistance to specify the span, and then when you check it in regionDidChange, you're seeing at the lat/long span, which is how it is stored in an MKCoordinateRegion struct.
As far as I know, the integer zoom levels are not available or useful at all when working with MKMapKit. I personally prefer using the span figures, its more flexible.
You cannot specify max and min zoom, and I don't know of a way to hack it in. MKMapKit is actually pretty weak right now, I'm pretty disappointed by the lack of features.
A quick comparison of zoom levels for a location using maps.google.com by inspecting the link querystring shows that the dx and dy span values increase by a factor of 2:
(0.005334, 0.011834) starting span
(0.010668, 0.023668) dx: x2, dy: x2
(0.021335, 0.047337) dx: x2, dy: x2
(0.042671, 0.094671) dx: x2, dy: x2
...
Brant's category on MKMapView works well. However, it appears that it has not been updated to support newer devices with retina screens when calculating mapSizeInPixels.
It can be fixed by replacing this line:
CGSize mapSizeInPixels = mapView.bounds.size;
With this line:
CGSize mapSizeInPixels = CGSizeMake(mapView.bounds.size.width * [UIScreen mainScreen].scale, mapView.bounds.size.height * [UIScreen mainScreen].scale);