Skip to content

Instantly share code, notes, and snippets.

@marmelroy
Created April 20, 2016 15:58
Show Gist options
  • Save marmelroy/0fee54bfe69bfbfcbbf7057298fca046 to your computer and use it in GitHub Desktop.
Save marmelroy/0fee54bfe69bfbfcbbf7057298fca046 to your computer and use it in GitHub Desktop.
Calculating MKMapCamera's altitude for a distance
let altitude = distance*tan(M_PI*(75.0/180.0))
@plindberg
Copy link

Thanks for this, it helped me figure out how to do this.

However, I’m not sure where 75.0 comes from, how it relates to the 30° aperture of the map camera you refer to in your tweet.

I have verified that the aperture indeed is 30° (see code snippet below), and have also discovered that MapKit is off by a factor of ≈1.55 in MKMapView.cameraZoomRange – which I explain in this StackOverflow post.

Anyway, here’s my solution:

// The aperture of the MKMapCamera isn’t documented, but there are reports here and
// there of this being the case. And we have established this by telling the map to
// focus on a specific latitudinal distance (because that’s the longest dimension),
// and then checking the centre coordinate distance of the camera. The aperture can
// then be calculated by `2 * atan(latitudinalDistance / 2.0 /
// mapView.camera.centerCoordinateDistance) * 180.0 * .pi`, which gives ≈30.00.
// Converted to radians for the calculation below.
let mapCameraAperture = 30.0 * .pi / 180

// Because the map view isn’t square, we need to adjust for the aspect ratio.
let aspectRatio = Double(bounds.size.height / bounds.size.width)

// For some reason, the camera zoom range is off by a factor ≈1.55. That is, if
// you set the minimum to 2500, and then zoom as far in as you can, the camera
// reports a center coordinate distance of ≈1610. Verified on iOS 13 and 14, in
// the simulator and on device. (https://stackoverflow.com/q/64352591/446328)
let mapKitBugAdjustmentFactor = 1.55

let minCameraDistance = (minLongitudinalMeters * aspectRatio) /
    (2 * tan(mapCameraAperture / 2)) * mapKitBugAdjustmentFactor

mapView.cameraZoomRange = MKMapView.CameraZoomRange(
    minCenterCoordinateDistance: minCameraDistance)

@AlekseiR
Copy link

AlekseiR commented Jul 6, 2021

@plindberg
Thank you. I've found a related answer on stackoverflow and came up with quite a similar solution.
https://stackoverflow.com/a/21034410/6292624

Wanted to update that on my devices (iOS 13) and simulators (13, 14) max zoom never causes that much delta with target value. In my case minCenterCoordinateDistance ~875 and max zoom value is ~890, so probably mapKitBugAdjustmentFactor should be removed or significantly reduced.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment