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

Symbols: fix translation, variable-anchors and collision boxes #4071

Merged
merged 36 commits into from
May 15, 2024

Conversation

kubapelc
Copy link
Contributor

@kubapelc kubapelc commented May 3, 2024

This is a port of the symbol bugfixes from: #4067 The porting ended up being relatively straightforward :)

Fixes #210 (as far as I can tell)

Fixes #3456

Changes (same as the bugfixes in the globe PR)

  • Fixed symbol collision debug view (showCollisionBoxes) not showing the actual bounding boxes used for collision and click areas. The displayed boxes now match actual collision boxes exactly. Displayed collision boxes will react to map motion with some latency. (Just as the actual collision boxes do.)
  • Fixed symbol collisions using inaccurate and sometimes entirely wrong collision boxes when the map is pitched or rotated. (#210)
  • Fixed symbol collision boxes not being accurate for variable-anchor symbols.
  • Fixed icon collision boxes using text-translate property for translation instead of the correct icon-translate.
  • Fixed text-translate and icon-translate behaving weirdly and inconsistently with other -translate properties. (#3456)
  • Updated some old render tests to reflect new symbol & collision box behaviour, added several new render tests

A screenshot of many, many collision boxes.

Launch Checklist

  • Confirm your changes do not include backports from Mapbox projects (unless with compliant license) - if you are not sure about this, please ask!
  • Briefly describe the changes in this PR.
  • Link to related issues.
  • Include before/after visuals or gifs if this PR includes visual changes.
  • Write tests for all new functionality.
  • Document any changes to public APIs.
  • Post benchmark scores.
  • Add an entry to CHANGELOG.md under the ## main section.

@codecov-commenter
Copy link

codecov-commenter commented May 3, 2024

Codecov Report

Attention: Patch coverage is 94.62500% with 43 lines in your changes are missing coverage. Please review.

Project coverage is 63.32%. Comparing base (4abf018) to head (dc4b7a4).
Report is 10 commits behind head on main.

Files Patch % Lines
src/symbol/placement.ts 93.83% 8 Missing and 6 partials ⚠️
src/geo/projection/projection.ts 81.48% 4 Missing and 6 partials ⚠️
src/symbol/projection.ts 94.25% 6 Missing and 4 partials ⚠️
src/symbol/collision_index.ts 96.82% 0 Missing and 6 partials ⚠️
src/symbol/symbol_layout.ts 0.00% 2 Missing ⚠️
src/render/draw_symbol.ts 98.68% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #4071       +/-   ##
===========================================
- Coverage   86.43%   63.32%   -23.11%     
===========================================
  Files         241      239        -2     
  Lines       32535    32791      +256     
  Branches     2001     1241      -760     
===========================================
- Hits        28121    20766     -7355     
- Misses       3458    11238     +7780     
+ Partials      956      787      -169     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@kubapelc
Copy link
Contributor Author

kubapelc commented May 3, 2024

A render test tests\icon-text-fit\textFit-grid-long is failing on Windows, but it seems to a an issue in the unmodified main as well. A build test seems to fail, I'm not sure why.

I've also noticed that pitch-alignment: map texts also have their collision boxes slightly off, even in mercator projection. Since it is not a globe-only edge case after all, I would like to try to debug it and fix it, please wait with merging until that gets fixed.

src/symbol/placement.ts Outdated Show resolved Hide resolved
src/symbol/projection.ts Outdated Show resolved Hide resolved
@HarelM
Copy link
Member

HarelM commented May 3, 2024

This looks amazing! Thanks! I still need to wrap my head around what you did, so any illustration of how the code used to work vs now would be helpful for me to understand.
Consider using mermain for that as github supports is natively now.

@kubapelc
Copy link
Contributor Author

kubapelc commented May 3, 2024

At this point I'm not sure myself about how it all works now, this is an accumulation of small changes and tweaks since about January. Most of the bugged behaviour was about some part of symbols not respecting translation or pitch alignment or rotation alignment properly, I think.

@HarelM
Copy link
Member

HarelM commented May 3, 2024

@ChrisLoer any chance you might be able to look at this PR? It would help a lot I believe.
I know you introduced some changes which touch this very code in a previous PR:

So your help would be greatly appreciated here.

src/symbol/projection.ts Outdated Show resolved Hide resolved
src/symbol/projection.ts Outdated Show resolved Hide resolved
src/symbol/placement.ts Outdated Show resolved Hide resolved
src/symbol/placement.ts Outdated Show resolved Hide resolved
@HarelM
Copy link
Member

HarelM commented May 15, 2024

Seems like some render tests are failing, can you please check why?
I left a few last comments.

src/symbol/projection.ts Outdated Show resolved Hide resolved
@HarelM
Copy link
Member

HarelM commented May 15, 2024

Is there a way to benchmark this to make sure we didn't create any performance issues?

@HarelM
Copy link
Member

HarelM commented May 15, 2024

Added a few comments after looking at the coverage report, which looks great BTW, good job on that!

@kubapelc
Copy link
Contributor Author

kubapelc commented May 15, 2024

I've added a benchmark that measures the performance of adding symbols to the collision grid and compared this branch to main.

When testing 20K symbols and adding all non-colliding symbols to the grid (as normal symbol placement would), I got ~170 ms on this branch compared to 90-100 ms on main.

When testing 20K symbols and only testing the collision box projection (replacing the grid test with a empty function), I got ~42 ms on this branch, compared to ~3 ms on main.

Only the second test is now present, the first is in my branch's commit history.

Analysis

I'm not sure how much merit the first test has, since the old collision box projection was pretty broken, so a lot of the performance difference might be caused by the collision grids being filled with different contents.

The second test shows that the accurate projection of collision boxes has a lot of overhead compared to the old approach. But the old approach basically only did 4 additions and 4 multiplications per box.

Both tests use 20K symbols, which is pretty extreme, I'd expect a typical map to have roughly 100x less symbols. Extra cost due to accurate projection would then be 0.4 ms. This is probably not worth optimizing further, especially with the assumption that symbol placement runs asynchronously in a separate thread, so it would not slow down rendering.

Edit: symbol placement isn't asynchronous, as pointed out by a newer comment.

Copy link
Member

@HarelM HarelM left a comment

Choose a reason for hiding this comment

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

THANKS!

@HarelM HarelM merged commit a548083 into maplibre:main May 15, 2024
15 checks passed
@ChrisLoer
Copy link
Contributor

This is probably not worth optimizing further, especially with the assumption that symbol placement runs asynchronously in a separate thread, so it would not slow down rendering.

Is that asynchronous assumption based on work in progress somewhere else? I just did a quick check and it looks to me like placement still follows the logic I remember: synchronous in the main/rendering thread, but with logic in pauseable_placement to pause itself if it goes over 2ms and continue the work in the next frame. That is, there's still a safety valve to try to keep slow placement from causing dropped frames, but it's not asynchronous.

.4ms is definitely enough to matter, but as you said that's with a pretty large set of symbols -- and fundamentally this functionality is going to require some extra computation, so it doesn't seem terrible to me.

@kubapelc
Copy link
Contributor Author

kubapelc commented May 16, 2024

Is that asynchronous assumption based on work in progress somewhere else?

Hi, no, I'm dumb and only remembered that collisions somehow don't slow down main rendering or happen alongside it, and assumed that it is asynchronous. You are of course right.

The 0.4 ms figure is an estimate of how long would 200 symbols take. Actually running the benchmark with 200 symbols takes 0.6 ms.

(Also since we are now looking at the absolute time of the benchmark: I ran it in Firefox on a 2.8 GHz Intel Core 7th gen, with turboboost disabled. No idea how that compares to common phone CPUs performance-wise.)

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