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

Change zoom precision function #5084

Merged
merged 1 commit into from
Aug 18, 2024

Conversation

AntonKhorev
Copy link
Collaborator

This changes the number of fractional digits to log10(pixels / degrees) with pixels = 2**(8 + zoom) and degrees = 180.


If you apply the entire #5064, zoom in to the max zoom level, place an endpoint marker and try to drag it around, you'll notice it moves by jumping several pixels. This is because I limit its coordinates to zoom precision and zoom precision is not high enough. Its current version was introduced in b28511f. You can notice something strange about it: the zoom value went from being an argument of Math.pow to an argument of Math.log. zoom is already on a log scale, why do you need to take its log again?

zoom old zoomPrecision new zoomPrecision
0 0 1
1 0 1
2 1 1
3 2 2
4 2 2
5 3 2
6 3 2
7 3 3
8 3 3
9 4 3
10 4 4
11 4 4
12 4 4
13 4 5
14 4 5
15 4 5
16 4 5
17 5 6
18 5 6
19 5 6
20 5 7
21 5 7

Some layers go up to zoom 21, precision limits become very noticeable there. Even on level 0 you need at least one digit after . to translate -90..+90 to 256 tile pixels.

@tomhughes
Copy link
Member

I'm not disputing there may be a problem here but it would be good to understand how you have derived the new formula you're using - the fact that the output repeats some values 3 times and some 4 times seems a little to me and suggests that the formula is slightly off somewhere causing rounding issues?

@AntonKhorev
Copy link
Collaborator Author

ceil( log10(2**(8+zoom) / 180) )

2**(8+zoom) = world size in pixels
180 = span of latitude values
2**(8+zoom) / 180 = number of pixels in one degree. If there are 100 pixels in one degree, you need log10(100) = 2 fractional digits to represent a degree value for a given pixel offset

@AntonKhorev
Copy link
Collaborator Author

AntonKhorev commented Aug 16, 2024

repeats some values 3 times and some 4

Because numbers are base-ten not base-some-power-of-2 and zoom levels magnify by powers of 2. On average numbers are repeated log2(10) times.

@tomhughes
Copy link
Member

ceil( log10(2**(8+zoom) / 180) )

Would it not be better just to use that then? Yes I can prove using logarthmic identities that what you've written is the same but it's not clear why you prefer the transformed version?

I also suspect the Math.max is no longer needed as it can't go negative for any sane zoom - it was needed before because log10 breaks down for zoom zero...

This changes the number of fractional digits to log10(pixels / degrees) with pixels = 2**(8 + zoom) and degrees = 180.
@AntonKhorev
Copy link
Collaborator Author

If you don't mind raising something to a variable power* and taking a logarithm of the result, here's a more readable version.

* could have used pixels = 1 << (8 + zoom), not sure if it's more clear

@tomhughes
Copy link
Member

Thanks. I think that makes it a lot clearer what is going on for future maintainer.

@tomhughes tomhughes merged commit 9bfae01 into openstreetmap:master Aug 18, 2024
24 checks passed
@AntonKhorev AntonKhorev deleted the zoom-precision branch August 19, 2024 09:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants