Skip to content

PhungVanHoa/map-angle-perspective

 
 

Repository files navigation

Problem

How to transform the camera such that the bounds are centered on screen at the greatest possible zoom level while the map is tilted.

Warning: For simplicity I'm assuming the map bearing is 0 (facing north), solving it for other bearings would just mean to add one more rotation matrix on y

Please let me know if there is a simpler solution I didn't see :)

Preview

zoom

Explanation

The way I approached this problem is by transformation matrices. Similar to what CATransform3D does with CALayers. So the way I formulated the problem is: assuming the rect (coord bounds) is centered on the screen at the greatest possible zoom with pitch=0 what transformation we need to apply so after applying the rotation, the rect ends up vertically centered and the resulting width equals the map width.

So the transformation needed would be: (Translation x Scale x Rotation x Perspective); where:

solution-transform-matrix

... t and s are the values we need to solve our system of equations for, p can be eye balled to 1 / -1350 and a is the pitch angle in degrees. Note that the z dimension is zero on the scale matrix which will simplify the math a bit and we don't need the z dimension here.

One more thing before moving on: because the rotation point needs to be in the center, we need to translate the matrix before transforming it (and after), so the resulting system would be:

solution-transform-matrix-full

... where h is the height of the bounds in pixels. After resolving this matrix we get:

solution-matrix

Next in order to get the projection of a point from the non-tilted rect to the tilted rect we use a function P(x, y) which looks like:

solution-px-and-py

Now the base equations for solving t and s are:

To fit to the width

  1. The top-left point of the new transformed rect (in 2D) should match (height / 2 - newRectHeight / 2) to be in the center.
  2. The width of the new transformed rect should match the container view.

solution-system-width

.. where:

  • w is the width of the rect to be transformed
  • W is the width of the container view
  • h is the height of the rect to be transformed

Now if we solve the system of equations with all this information we obtain:

solution-for-t-s-width

To fit to the height

  1. The top-left point of new transformed rect should be (0, 0)
  2. The height of the transformed rect should match the container view's height

solution-system-height

... where h is the height of the rect.

solution-for-t-s-height

These four equations is all the math we need to calculate the translation and the scale values. With this we can apply the scale to the bounds distance and calculate the zoom and offset the center using t (see implementation)

About

Sample project to show how to calculate tilted bounds to fit coordinates

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Swift 98.9%
  • Ruby 1.1%