Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: camera elevation #3552

Open
IvanSanchez opened this issue Nov 7, 2016 · 11 comments
Open

Feature request: camera elevation #3552

IvanSanchez opened this issue Nov 7, 2016 · 11 comments

Comments

@IvanSanchez
Copy link
Contributor

Motivation

With extruded geometries, there are use cases where the focus should be on a specific elevation.

The most obvious is to focus on a building rooftop with a call to Map#flyTo. With more 3D data, users might want to have a control to travel "up" and "down" besides moving N-S-W-E.

Design

I suggest a new property in CameraOptions, named height or elevation, e.g.:

map.flyTo({
  center: [ 63.5, 10.4 ],
  zoom: 17,
  bearing: 15,
  pitch: 45,
  elevation: 100  // assumed meters, or CRS units, as in the extrude height
})

Implementation

I guess the internal camera state shall store the camera elevation somewhere, and modify the 3D transform matrix as appropriate.

This might change the viewport bounds, so the calculations for the tile ranges might change as well (my knowledge of the internals of this project is low, so I don't know if the 3D transform matrix is reused for this purpose).

Any easing function for the camera state (flyTo animations and the like) shall also ease and interpolate the elevation.

@1ec5 1ec5 added the GL native → GL JS For feature parity with Mapbox Maps SDK on a native platform label Nov 15, 2016
@1ec5
Copy link
Contributor

1ec5 commented Nov 15, 2016

First of all, any elevation option would be mutually exclusive with the existing zoom option, because they’re competing ways of scaling the map. Zoom level–based APIs are appropriate for aligning with a given function stop in a style layer, whereas altitude-based APIs are appropriate for aligning to real-world features. (This is, after all, a map rather than an image viewer.)

Specifically, imagine you want to set a camera that comfortably clears the tallest building in a city. You could do it in one line by saying you want a camera with a certain altitude. Or you can guess and check until you come up with the right zoom level. But guessing and checking only works if you hard-code a specific city and a specific building.

flyTo demonstrates this point nicely. A developer can only intuit a value for the minZoom option if they’ve designed the map themselves and want to ensure that a certain function stop is reached. But if the goal is to simulate aircraft flying at a certain altitude – say, for a game – a peakAltitude option would be far more intuitive.

The Mapbox iOS and macOS SDKs have an implementation of the requested feature in the altitude property of MGLMapCamera. You can set the map’s zoom level, or you can set the altitude, but not both at the same time. For a tilted map, you can create the camera in two ways: either based on the viewer’s height above the ground or based on the center point’s viewing distance (since Mapbox GL doesn’t offer any way to change the focal point). Unfortunately, the conversion between zoom levels and altitudes is fraught, but there would be a real benefit for developers who need animations with a relation to the real world.

@ansis
Copy link
Contributor

ansis commented Nov 15, 2016

@1ec5 I agree with what you wrote but I understood the request slightly differently. You're thinking about the altitude of the camera but I think @IvanSanchez is asking about the altitude of the point the camera is looking at. This fits in which the current CameraOptions which describes what the camera is looking at and how, not where the camera is.

Right now you can only say "look at the point at 0m above ground level at [-79.3, 43.6]" but the suggestion is to support saying "look at the point at 100m above ground level at [-79.3, 43.6]".

I think this makes sense to support.

Changing the 0 on this line in transform.js should be what we need on the projection side.

Tile loading might automatically adapt or it might need some changes. And once that is working, if you set it to something too high for the current zoom it will try to load too many tiles. We need a temporary limit on this. The level-of-detail tile loading we need to implement for pitched view should let us remove this limit eventually.

@1ec5 1ec5 removed the GL native → GL JS For feature parity with Mapbox Maps SDK on a native platform label Nov 17, 2016
@IvanSanchez
Copy link
Contributor Author

I think @IvanSanchez is asking about the altitude of the point the camera is looking at.

Yes, yes, yes, yes. Sorry if I was unclear in my first explanation.

The main use case I have in mind is being able to perform flyTo calls which centers the map on building rooftops, not on the building footprints, regardless of tilt and bearing.

@adamduncan
Copy link

Hey @ansis, @IvanSanchez, has there been any more exploration of this approach? Am currently working on fitBounds-ing some polygon extrusions with known heights, but it's all a bit chicken and egg.

@TheMapSmith
Copy link

Hi everyone, I'm thinking about something similar for an app I'm working on. I'm animating airline flights and I'm wanting to make it roughly POV from the airplane. I was hoping for an altitude parameter in AnimationOptions or CameraOptions so I can vary the view across the flight from takeoff to cruising to landing.

@strangerintheq
Copy link

Voting up for this feature.
In case of showing of buildings overlaying mapbox.

@andrewharvey
Copy link
Collaborator

andrewharvey commented Sep 27, 2019

I've hacked together some code to workaround the lack of core support
https://bl.ocks.org/andrewharvey/a0b56df5d605d86facc3da9723a9ef6e. It will find the corresponding map center/zoom to use to look at a point at an elevation. It's not the best code, and might not cover all cases, but it seems to work okay so far.

@1ec5 and @ansis raise good points in #3552 (comment) and #3552 (comment)

First of all, any elevation option would be mutually exclusive with the existing zoom option, because they’re competing ways of scaling the map. Zoom level–based APIs are appropriate for aligning with a given function stop in a style layer, whereas altitude-based APIs are appropriate for aligning to real-world features. (This is, after all, a map rather than an image viewer.)

Specifically, imagine you want to set a camera that comfortably clears the tallest building in a city. You could do it in one line by saying you want a camera with a certain altitude. Or you can guess and check until you come up with the right zoom level. But guessing and checking only works if you hard-code a specific city and a specific building.

True. My suggestion would be when passing a [lng, lat, altitude] to jumpTo/flyTo you would also need to pass a cameraHeight instead of a zoom. The cameraHeight would be how high do you want the camera when looking at [lng, lat, altitude]. A nice result for 45deg would be 2 x altitude, and it would pick out the corresponding zoom value. Or it would be distanceFrom as they are equivalent, just something in real world units, not zoom levels.

Changing the 0 on this line in transform.js should be what we need on the projection side.

Hmm, but won't that then mean that map.getCenter() is no longer the point in the middle of the screen? (update: when pitch is not 0)

@andrewharvey
Copy link
Collaborator

See also #6093

@asheemmamoowala
Copy link
Contributor

The free camera, via FreeCamerOptions now allows defining the position of the camera with elevation, but the look at point is still based on 0 elevation.

@SkylinR
Copy link

SkylinR commented Jan 15, 2022

PROBLEM DESCRIPTION
Hi :) I'm trying to display some popular buildings on map. (I need to disable by ID some default buildings and replace them with my owne models). And it's working like a charm but I get ID of that default buildings on some zoom (from 16, on higher zoom like 15.9 I cannot get ID of that single default building to replace it). So I'm there with zoom 16 and I want to display Burj Khalifa but this is quite high building and it's not visible entirely. I'm trying to change elevation to look a little bit higher then base of building to be able to display it whole on screen and there is my PROBLEM. As far as I can see all those elevation/altitude solutions works on zoom and when I'm trying to use it at the end of the day it changes map zoom (what makes default building visible and I cannot disable it because on higher zoom I cannot disable that single default building).
Aditionally I'm rotating camera around that point :D so it's important to not just setup one view but it must be visible from each side (if that's important)

MY QUESTION
Is there any option to just make camera look on point like "over" map a little bit.

@Bulisor
Copy link

Bulisor commented Feb 9, 2023

The free camera, via FreeCamerOptions now allows defining the position of the camera with elevation, but the look at point is still based on 0 elevation.

Hey, what about look at point? Is there a way I can set it at a specific altitude? Thank you

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

No branches or pull requests