Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Exploring designs: thicker lines unzoomed#782

Draft
dabreegster wants to merge2 commits intomain
base:main
Choose a base branch
Loading
fromunzoomed_sketch

Conversation

dabreegster
Copy link
Collaborator

Problem: in larger maps, scaling routes in map-space stops looking reasonable when you zoom far out:
before

Possible solution: thicken polylines and scale up circles as we zoom out:
after

The first question: does this look better? Is it more usable?

How to implement: ad-hoc + caching

This PR does an ad-hoc approach, discretizing zoom like we do for labels and the bike network layer, then recalculatingeverything when that zoom changes. The outer-most / application level has to be aware of zoom and trigger recalculating everything. If we want to actually cache drawables and theWorld per discretized zoom instead of just storing one at a time, the code probably gets even grosser.

Alt: abstract with something likeToggledZoomed

ToggleZoomed hides the fact that one of two things get drawn, based on zoom. App-level code just treats it as something drawable; it's simpler from that perspective.

Could we generalize? The performance-intensive but simple answer is to precalculate things for all of the discretized zoom levels upfront, and just switch between them. This might be quite slow; every single time we want to redraw a route as we drag a waypoint around, we would thicken a polyline not just once, but 5 or 10 times! Even though it's unlikely that the zoom level is changing as we drag.

The less simple approach would have some kind of app-level callback to regenerate aGeomBatch given a zoom or thickness parameter as input. The lifetimes / borrowing rules might make this tricky. For example, if aState struct contains thisCacheZoomed helper, and to calculate for a new zoom level, we need to borrow all of the fields in theState struct, we might have a double borrow problem, like we have withCached today sometimes.

Another problem with this approach

The second complication is that sometimes we don't want to just recalculate something to draw based on zoom; we also need its hitbox to click on it. The polygon editor recently changed to use the newWorld API, but we scale everything there based on zoom, so we recalculate the entireWorld for different zooms:

world:Cached<f64,World<Obj>>,

If we wanted to stop recalculating everything for different zooms (the ad-hoc + caching approach described earlier, aka, this PR), we might need to teachWorld how to do this natively. Maybe it can handle adjusting the quadtree and drawables as needed.

Builder API

The common case is thickening polylines different amounts. Maybe we can make an object that holds onto the polyline, base width, and color, then generates the scaled stuff as needed.

Except it's rarely that simple. In this PR, we also see examples of needing to scale circles and text for the waypoints. And for drawing alternate routes, we need to turn a thickened polyline into an outline/border too. It seems more general-purpose and simple to write a function to draw stuff, given a zoom/thickness.

Alt: Shader?

We just have one shader today that can translate and scale stuff. For drawing in "screen-space", we just temporarily override the parameters for those. Should we start a second shader designed to draw things that have a certain map-space position, but can scale up? Can this work for anything in general (circles, text, thick polylines), or would it just be for polylines? How does it work -- always draw things with a certain size on the screen -- like a polyline with 10 pixels thickness -- but adjusting the position to match the current camera?

I need to find examples of how most maps handle this today.https://mattdesl.svbtle.com/drawing-lines-is-hard "expanding in a vertex shader" looks like a good lead.

Pushing this into the shader doesn't solve everything -- what about hitboxes for clicking the unzoomed route? Maybe we have a new structure, that plays withWorld, that remembers the original polyline and base thickness, projects the cursor onto the nearest line segment, and checks if that distance is within the current threshold.

…changes.Again, looks decent... (except for drawing intersection polygons forsome extra detail layers)
@dabreegster
Copy link
CollaboratorAuthor

dabreegster commentedOct 15, 2021
edited
Loading

https://deck.gl/docs/api-reference/layers/line-layer is exactly the effect I'm trying to achieve -- the line is always the same thickness in screen-space.https://github.com/visgl/deck.gl/blob/8.6-release/modules/layers/src/line-layer/line-layer-vertex.glsl.js looks simple enough...

Copy link
Collaborator

@michaelkirkmichaelkirk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I agree with the possible approaches. I don't really have an opinion on which one makes the most sense right now.

I think the shader approach is the one that will ultimately look best in motion and at rest while having good performance. But it also sounds complex - especially around mouse/hitbox interactions.

The currently proposed changes seem to be only about solving the line-thickness problem, and not other things, like text or texture scaling, right?

Just in case you missed it, Brandon Liu recently posted a nice article about some similar stuff:https://bdon.org/blog/web-map-performance/

@@ -4,12 +4,16 @@ use widgetry::{Color, Drawable, EventCtx, GeomBatch, GfxCtx, Line, TextExt, Widg

use crate::app::App;

const RADIUS: Distance = Distance::const_meters(10.0);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

What is this a radius of? The waypoint markers?

@dabreegster
Copy link
CollaboratorAuthor

Just recordinghttps://github.com/bbecquet/Leaflet.PolylineOffset. I think the base leaflet line drawing behavior (maybe with this library, maybe without) is good reference. The bus demo is quite nice at all zoom levels.

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@michaelkirkmichaelkirkmichaelkirk approved these changes

@xorozoxorozoxorozo approved these changes

Assignees
No one assigned
Labels
None yet
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

3 participants
@dabreegster@michaelkirk@xorozo

[8]ページ先頭

©2009-2025 Movatter.jp