cc @1ec5
To recap: fitBounds does not account for the trapezoidal shape of the bounds when the map is tilted. As a result, the map鈥檚 camera fails to round-trip correctly (tending to zoom out) when the map starts out tilted.
This issue tracks the work to make Map::cameraForLatLngs() visually fit to the passed-in bounds when the map is tilted. To illustrate the problem, I rigged iosapp to:
visibleCoordinateBoundscamera, adjusting its pitch, and setting camera to that modified camera)-[MGLMapView setVisibleCoordinateBounds:animated:]The result is that the map is zoomed much farther out than it should be:

There are a couple possible behaviours in some cases. Imagine a box that's a horizontal line. It has a large width and small height. You could:
Which is better? I prefer the second.
Absent tilt, you can think of the current behavior as a) centering the shape, then b) zooming to fit (but not panning or rotating). So I鈥檇 prefer (2) as well. In the future, we could choose an optimal rotation and pitch for a given object, similar to what the Bing Maps API does, but that would have to be a separate method.
On iOS, when the map is tilted and you enter targeted course tracking mode (in which both the user location and a target coordinate are fitted to opposite ends of the map view), cameraForLatLngs() underzooms, so the map bounces back and forth as it iteratively settles on the correct bounds.
Confirmed an issue on Android as well. When the map is tilted and you try fitting the camera within a bounds, it doesn't take into account the tilt.
LatLngBounds latLngBounds = new LatLngBounds.Builder()
.include(new LatLng(36.532128, -93.489121)) // Northeast
.include(new LatLng(25.837058, -106.646234)) // Southwest
.build();
mapboxMap.easeCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 50), 5000);
Full code can be found in the demo app.
This gif is suppose to fit the entire state of Texas within view but cuts it off only when the map is tilted before the animate camera is called:

cc: @zugaldia @ivovandongen
following this issue for: CameraUpdateFactory.newLatLngBounds() zooming to greatest possible zoom
We were facing a similar challenge; this is: How to transform the camera such that the bounds are centered on screen at the greatest possible zoom level while the map is tilted. I'm gonna share the solution I came up with in case is of any use to anyone. My example is using google maps (sorry!) and implemented on iOS but I think it might be useful regardless.
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 :)
EDIT: Fixed the math to use meters per pixel instead of calculate the % which leads to an almost pixel perfect implementation (see the preview) and moved the implementation to an example project. I also added the math for calculating the height fit cases

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:

... t and s are the values we need to solve our system of equations for, p can be eye balled to 1 / -(view.height * 1.875) 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:

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

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:

Now the base equations for solving t and s are:

.. where:
w is the width of the rect to be transformedW is the width of the container viewh is the height of the rect to be transformedNow if we solve the system of equations with all this information we obtain:


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

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)
see #13007. This may work for many of these cases.
I don鈥檛 think #13007 addresses this issue at all. mbgl::Map::cameraForGeometry() is just a convenience wrapper for cameraForLatLngs(), so it suffers from the same inaccuracy when the map is tilted.
This issue has been automatically detected as stale because it has not had recent activity and will be archived. Thank you for your contributions.
Most helpful comment
We were facing a similar challenge; this is: How to transform the camera such that the bounds are centered on screen at the greatest possible zoom level while the map is tilted. I'm gonna share the solution I came up with in case is of any use to anyone. My example is using google maps (sorry!) and implemented on iOS but I think it might be useful regardless.
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 :)
EDIT: Fixed the math to use meters per pixel instead of calculate the % which leads to an almost pixel perfect implementation (see the preview) and moved the implementation to an example project. I also added the math for calculating the height fit cases
Preview
Implementation (example)
See this view controller
Explanation
The way I approached this problem is by transformation matrices. Similar to what
CATransform3Ddoes withCALayers. 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:
...
tandsare the values we need to solve our system of equations for,pcan be eye balled to1 / -(view.height * 1.875)andais the pitch angle in degrees. Note that thezdimension is zero on the scale matrix which will simplify the math a bit and we don't need thezdimension 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:
... where
his the height of the bounds in pixels. After resolving this matrix we get: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:Now the base equations for solving
tandsare:To fit to the width
.. where:
wis the width of the rect to be transformedWis the width of the container viewhis the height of the rect to be transformedNow if we solve the system of equations with all this information we obtain:
To fit to the height
... where
his the height of the rect.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)