mapbox / mapbox-gl-js

Interactive, thoroughly customizable maps in the browser, powered by vector tiles and WebGL
https://docs.mapbox.com/mapbox-gl-js/
Other
11.11k stars 2.21k forks source link

Add optional elevation arguments for project()/unproject() #6415

Open peterqliu opened 6 years ago

peterqliu commented 6 years ago

I'd like to be able to incorporate altitude both when converting a pixel value to a lnglat coordinate, and vice versa. This would allow us to make calculations and reason about the map, in full 3D space. Example questions this would answer are:

map.project(lnglat, elevation): where on the screen would an object at this coordinate and this elevation appear?

map.unproject(px, elevation): Say I'm hovering on the rooftop of a building extrusion of known height. What's the ground coordinate that corresponds to this pixel value?

This would be an optional parameter that defaults to, and has a minimum of 0.

jussirantala commented 6 years ago

I would need this too. I'd use CSS3D to display my own labels etc on top of the map. Also z-coordinate would be nice.

jmlopez-rod commented 5 years ago

If possible, it would be nice to be able to provide zoom, pitch and bearing. This could allow us to do computations without changing the state of the map. Currently I've had to change the internals before calling unproject.

    const tr = map.transform;
    const currentPitch = tr.pitch;
    const currentAngle = tr.bearing;
    tr._pitch = 0;
    tr.angle = 0;
    tr._calcMatrices();
    // get the coordinate as if we were in 2D
    const coord = map.unproject(new Point(0, 0));
    // Return it to its original state
    if (currentAngle === 0) {
      tr.pitch = currentPitch;
    } else {
      // we only want to do one call to calcMatrices()
      tr._pitch = currentPitch / 180 * Math.PI;
      tr.bearing = currentAngle;
    }

By default those values would take the current values of the map.

ansis commented 5 years ago

@jmlopez-rod can you provide some examples of what you are trying to accomplish?

jmlopez-rod commented 5 years ago

@ansis In my leaflet code I was making a call to map.getBounds() in order to determine the maxBounds that I should assign the map. I want my map region to never disappear while still showing things outside the boundary. We cannot just set a maxBound from the get go because as we zoom in we will be able to make the region go out of view. For this reason I compute the bounds in display and based on that I add some padding to my region that I want to display in each zoom level.

When I used mapbox-gl everything worked well on 2D. I was able to set themaxBounds with each zoom level so that my map region always has some padding.

The problem in 3D is when I call getBounds I obtain a large region that doesn't have much meaning for my calculations. What I found was that if I still perform the same calculations as I did in 2D then the results I obtain work well on 2d and 3d.

Thus the "hack" I wrote above to always make the calculation as if the map was in 2D. If you have any ideas on how to obtain the bounds of the current map as if the pitch and bearing were 0 please let me know so that I can get rid of that monstrosity up there.