tangrams / walkabout-style

Preview map:
https://tangrams.github.io/walkabout-style
MIT License
32 stars 14 forks source link

Show path steepness #44

Open bcamper opened 8 years ago

bcamper commented 8 years ago

@nvkelso suggested we could try to show path steepness based on normal/elevation tile data.

We tried any initial prototype using the steepness of the terrain normal; deeper red means steeper terrain:

tangram-thu may 12 2016 15-13-14 gmt-0400 edt

But, this isn't really right, because the steepness of the terrain does not necessarily equal the steepness of the path, e.g. a steep path could be going up a mountain, but a relatively flat path could also simply be going around a steep mountain. We can see this in the path above N. Valley Trail, where the mountain itself is steep, but the path appears to be going alongside the mountain.

To know how steep the path itself is, we need to take the dot product of path direction and the terrain normal (actually the xy component of the terrain normal since path direction is 2D). That gives something that (on first glance) looks closer to what we might expect: that same path above N. Valley Trail is mostly flat, but you can see steeper red segments that correspond to variations in the terrain itself.

tangram-thu may 12 2016 16-15-32 gmt-0400 edt

This remains a prototype, however, more experimentation is needed to verify that this behavior is correct, and consider better ways to deal with caps ad joins on lines.

Another approach to consider, that may make more sense overall, is to just sample the raw elevation change of each path segment. There is no way to do that with existing Tangram pipeline though; options could include a) sampling the elevation in the vertex shader to create a custom varying and then measure the screenspace derivative of the elevation change (though there isn't 100% device support for vertex shader texture sampling, particularly on mobile devices), or b) a hook somewhere in the tile build process to do this CPU side (complicated by texture load timing and might imply a lot of new syntax that could be difficult to support cross-platform).

bcamper commented 8 years ago

Here's the current scene file I was experimenting with, for posterity:

terrain-path-steepness.txt

github only allows txt extensions, not yaml :/

nvkelso commented 7 years ago

(This would also be useful for bike map.)

bcamper commented 7 years ago

I'll dust off the test code and try it out again :)

bcamper commented 7 years ago

I've been looking at this with @meetar. There are two issues I'm unsure about that are holding back the quality/usefulness:

Here's a demo of current WIP, putting this down again for the moment - white path area is "flat", redder is steeper: https://mapzen.com/tangram/play/?lines=876-911&scene=https%3A%2F%2Fmapzen.com%2Fapi%2Fscenes%2F4%2F372%2Fresources%2Fwalkabout-style.yaml#16.0000/36.0887/-112.1627

bcamper commented 7 years ago

Here's a variant showing the surrounding terrain steepness - black is flat, whiter is steeper:

https://mapzen.com/tangram/play/?lines=999&scene=https%3A%2F%2Fmapzen.com%2Fapi%2Fscenes%2F4%2F373%2Fresources%2Fwalkabout-style.yaml#16.0000/36.0887/-112.1627

There's a uniform u_show_steepness on line 999 you can use to toggle that on/off.

nvkelso commented 7 years ago

This is super rad! Screenshots of San Francisco:

screen shot 2017-03-16 at 13 49 30 screen shot 2017-03-16 at 13 49 42

SRTM only terrain data doesn't fair so well (is too radar bumpy), here Munich:

screen shot 2017-03-16 at 13 50 42

I've made adjustments to the style here:

The key bits are:

Add the slope style to draw block, giving it width and order (this is for quick data exploration, would need to be reworked for final display):

    roads:
        draw:
            slope2:
                width: [[13,1px],[15,2px],[17,3m]]
                color: red
                order: function() { return feature.sort_rank +100; }
        path:
            draw:
                # not clear why this is needed again, and why width isn't 
                slope2:
                    width: [[13,1px],[15,6px],[17,3m]]    honored
                    color: red
                    order: function() { return feature.sort_rank + 0100; }
            footway:
                # because sidewalks are close to tall buildings, then the slopes are all wonky
                sidewalk-crossing:
                        slope2:
                            visible: false

The style is defined as:

styles:
    slope2:
        base: lines
        raster: custom
        shaders:
            blocks:
                global: |
                    varying vec2 v_path;
                position: |
                    v_path = abs(extrude.yx);
                color: |
                    vec2 path = normalize(v_path);
                    const float pathsegs = 2.;
                    path = floor(path * pathsegs) / pathsegs;
                    path = normalize(path);

                    vec3 terrain = (sampleRaster(0).rgb - .5) * 2.4;

                    float steepness = clamp(pow(dot(path, terrain.xy) * 16., 1.5), -1., 1.);
                    const float segs = 5.;
                    steepness = floor(steepness * segs) / segs;

                    color.rgb = mix(vec3(1.), vec3(1.,0.,0.), abs(steepness));
nvkelso commented 7 years ago

@patriciogonzalezvivo has another option that is more performant by removing stepping and setting the texture filtering to nearest:

here is w a ramp https://mapzen.com/tangram/view/?scene=https://mapzen.com/api/scenes/15/377/resources/walkabout-style.yaml#18.70648/37.76610/-122.44203

patriciogonzalezvivo commented 7 years ago

The colors on the ramp could be manipulated easily to transition over X number of colors + alpha. In that case is using just this 5 pixels long ramp https://github.com/opentraffic/tangram-viz-experiments/blob/gh-pages/assets/palette-01.png

nvkelso commented 7 years ago

And some further enhancements from @matteblair:

https://mapzen.com/tangram/view/?scene=https://mapzen.com/api/scenes/33/378/resources/walkabout-style.yaml#15.7897/37.7663/-122.4398

quote: Before I forget, here’s what I tried for the road slopes:

        base: lines
        raster: custom
        texcoords: true
        shaders:
            extensions: OES_standard_derivatives
            blocks:
                color: |
                    vec2 path = vec2(dFdy(v_texcoord.x), dFdx(v_texcoord.x));
                    path = normalize(path);
                    vec3 terrain = (sampleRaster(0).rgb - .5) * 2.;
                    float steepness = clamp(abs(dot(path, terrain.xy)) * 8., -1., 1.);
                    color.rgb = vec3(1., 1. - steepness, 1. - steepness);

It uses screen-space derivatives of a line’s texture coordinates to determine the direction of the line geometry more accurately than with the extrusion vector. The results looked good to me in the few places that I could check, but someone with more knowledge of the terrain should check it. endquote