MKMapView show extra zoomed region. How? - ios

I need to show very small area (30x30 meters) on MKMapView. Setting appropriate region or visibleMapRect doesn't work. MapView shows much bigger region.
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([centerLocation coordinate], 30, 30);
[mapView setRegion:region];
It seems with extra small regions MapView corrects with regionThatFits method before update map.
Manually zoom allows displaying such region.

MapKit is not really designed for such high-zoom indoor uses. You may want to check out alternatives such as the open source MapBox iOS SDK, which has been used for indoor applications. In particular iOS 7's iBeacons technology as well may be useful to you for indoor triangulation and higher accuracy than something like GPS, which was neither designed for indoor nor high-zoom use.

According to Apple docs:
When setting a new region, the map may adjust the value in the region
parameter so that it fits the visible area of the map precisely. This
is normal and is done to ensure that the value in the region property
always reflects the visible portion of the map. However, it does mean
that if you get the value of that property right after calling this
method, the returned value may not match the value you set. (You can
use the regionThatFits: method to determine the region that will
actually be set by the map.)
So, when you apply distance, it creates the region which is best fit for your request. It will not be exactly same as what you have requested.
Also, 30*30 meters is very very high zoom level which might not be supported. Hope it will help.

Related

How to limit map bounds in mapbox MGLMapView?

I'm using mapbox-iOS-SDK 3.2.3 and can't find any properties or smth like this to control the map bounds. I need to limit the visible area for the user. Is it possible in current SDK version?
There's nothing built in to the current version of Mapbox that looks like it would do what you want. You might be able to get something like it by
Implementing mapViewRegionIsChanging: or mapView:regionDidChangeAnimated: in the map view delegate
In those methods, check the current region. If it's outside the desired area, reset the map view to something inside the desired region. That is, as soon as the map view starts to move outside the region, make it go back.
This would probably work but it might make the view "stutter" if the user tries to scroll outside the target region. I don't know what your app does, but it might be worth considering (a) whether this is actually necessary and (b) whether there might be a better way to avoid whatever problem you expect than restricting map view scrolling.
I took the idea from #Tom Harrington and implemented the delegate with the goal of seeing how much stutter or animation jankiness there was while keeping a user within a known Mapbox bound. I upvoted his answer, but also wanted to share this example.
Here is a Swift delegate that fills out the delegate for mapViewRegionIsChanging
the main goal is to test if the experience is still pleasing to the customer (yes)
Can the delegate properly keep the user within bounds without calling the delegate too often? (still needs to be verified)
Uses Balboa Park, as a square Mapbox MGLCoordinateBounds
Only checks if the customer scrolls too far north
The concept of too far is checked by some tolerance, epsilon
Checking out of bounds on four sides should be straightforward
func mapViewRegionIsChanging (mapView: MGLMapView) {
let viewBounds = mapView.visibleCoordinateBounds
// Set the map's bounds to Balboa Park, San Diego
let boundsBalboaPark = MGLCoordinateBounds(
sw: CLLocationCoordinate2D(latitude: 32.71942, longitude: -117.15914),
ne: CLLocationCoordinate2D(latitude: 32.74093, longitude: -117.13374))
let deltaNorth = viewBounds.ne.latitude - boundsBalboaPark.ne.latitude
let epsilon = 0.025 // Magic number for tolerance of how far 'north' we allow (in degrees); Q.E.D meters
if( deltaNorth > epsilon) {
mapView.setVisibleCoordinateBounds(boundsBalboaPark, animated: true)
}
}
This animation shows moving the mapView too far north of Balboa Park. The stutter you see is real, but acceptable.

How to zoom to current location on map with Skobbler

I want to zoom to current user's location upon initialising SKMap.
Right now I don't know if it's even possible (even though it's impossible that it's impossible) but I fail to find the way through documentation.
Only thing I found is method for android
mapView.setZoom(int);
But there is nothing like it for iOS.
How can I zoom to the users current location then?
Simply create a region for your map to focus onto:
SKCoordinateRegion region;
region.center = CLLocationCoordinate2DMake(52.5233, 13.4127);
region.zoomLevel = 17;
mapView.visibleRegion = region;
I've never used SKMap before, but, yes you can simply obtain the user's location in iOS using CLLocationManager. I assume there's a function in SKMap by which you can zoom to a particular set of coordinates, to which you can simply pass the coordinates obtained from CLLocation Manager.

Can a map overlay be moved?

I'm displaying several user's locations on a map simultaneously as circles of different colors.
I can do this using an annotation and then when the user's location updates use UIView:animateWithDuration: to move to their new location.
However there is a requirement that the size of the circles reflects the accuracy of the location i.e. very accurate equals a circle of size 10 meters, rough accuracy is represented as a circle of size 500 meters etc.
However there are two problems using annotations for this - the first is how to transform meters into a CGRect on the correct size to draw on the map. And the second is the annotations need to be resized if the user zooms the map.
So I was looking at using an overlay instead as that already has a radius and automatic resizing during zooming built in so it handles those two problems.
However it looks like overlays are meant to be static and their coordinate property is read only.
Is there some way I can make the overlays move as the user's location moves? (other than completely remove it and re-add it?)
[THis is for iOS 7 only]

MKMapView zooms itself out

This is a small method of mine which takes the location manager's current location and focuses the map just a little bit above it to make room for some other subviews that I've added to the top of the map. If the span's lat/long deltas get too big (more than 1.0), every time the region is set, the span gets bigger and bigger until the map is zoomed out all the way, even without actually touching the map. I think it has something to do with reusing the map view's span, but I don't know exactly what's going on.
- (void)setRegion {
CLLocationCoordinate2D coord = locationManager.location.coordinate;
MKCoordinateSpan span = mapView.region.span;
coord.latitude += 0.002 * (span.latitudeDelta / 0.012523);
MKCoordinateRegion region = MKCoordinateRegionMake(coord, span);
[mapViewGlobal setRegion:region animated:animated];
}
From Apple's docs "If you want to change the center coordinate without changing the zoom level, use the setCenterCoordinate:animated: instead." MKMapView
- (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated
MKMapView will pick a new region that nicely fits the to a redefined zoom level while still displaying your entire target region and each time yo move north the span changes and things spiral out of control.
Also, your way of working out how much to change the latitude by is a bit odd. Aside from doing a multiple and divide when one would do the trick, it'll only work at a certain latitude (they get stretched away from the equator) and a certain zoom level. You'd be better off working out how many pixels you need the map scrolled by (presumably half the height of your subviews) and then using this function to work out where you need to center the map.
- (CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(UIView *)view
Another way would be to put the subviews outside of the MKMapView, but that'll affect your aesthetics.

Is there any way to programatically zoom MKMapView without it snapping to one of its predefined zoom levels?

I am using setRegion to have MKMapView zoom in to the region I have supplied. The problem is that there is very little granularity to this and it simply chooses the most proximate zoom-level and zooms to that.
Is there any way of having it zoom to exactly the region I have supplied or do I need to accept this limitation and move on?
No, currently it zooms so that the map tiles aren't blurry, which means fixed zoom levels. The upcoming update seems to render on the fly, so you may be able to do it in the future, but for now you'll have to accept the region you get.

Resources