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

Non-existent zoom on an overlay. #33

Closed
ravenfeld opened this issue Jan 3, 2022 · 21 comments
Closed

Non-existent zoom on an overlay. #33

ravenfeld opened this issue Jan 3, 2022 · 21 comments

Comments

@ravenfeld
Copy link

ravenfeld commented Jan 3, 2022

Hi, I try to display a background with an overlay, if the 2 have the same zoom availability I have no problem but I would like that if one of the 2 maps does not have a zoom that it continues to be displayed but with the old zoom.
The problem is that I do the overlay in getTileStream, maybe it's a mistake?
Can we find the previous zoom and row and col value in the getTileStream method?
I'm using a tile database and I don't have all the zoom so you can understand my request better.

Thank you in advance for your response

In french

Bonjour, j’essai d’afficher un fond avec une sur-couche. Si les 2 ont la même disponibilité de zoom je n’ai pas de souci mais j’aimerais que si l’une des 2 cartes n’a pas un zoom qu’elle continue a s’afficher mais avec l’ancien zoom.
Le problème est peut etre lié au faite que je fais la sur couche dans getTileStream c’est peut être une erreur ?
Peut on trouver le zoom précédent et la valeur row et col dans la méthode getTileStream ?
J'utilise une base de donnée de tuile et je n'ai pas tout le zoom pour que tu comprennes mieux ma demande.

Merci d'avance de votre réponse

@p-lr
Copy link
Owner

p-lr commented Jan 3, 2022

Hi,

I'm not sure I follow, even though I get a sense of what you're trying to achieve.
MapView automatically subsamples tiles when zooming out, so even if tiles aren't available at low scale, tiles from the last available level are rendered (and subsampled). However, MapView does not fill gaps between levels themselves.
About overlaying, it looks like you did well by implementing that inside the TileStreamProvider, since MapView can only have one TileStreamProvider.

Perhaps you could fork the project, edit one of the demos and showcase the problem you're having? It would be much easier for me to provide advice.

P.S: I'm french, yes, but we can communicate in English (so that other people understand this conversation).

@ravenfeld
Copy link
Author

ravenfeld commented Jan 3, 2022

I'm trying to render via a sqlite tile database. Except I didn't put all the zooms. I would like to have no white area when a zoom is not available. I have the problem as soon as I move the map.
In the demo if you delete the zoom 3 directory and the requests are on this zoom you will have only a white card when moving.

@p-lr
Copy link
Owner

p-lr commented Jan 3, 2022

Taking your example, if we zoom in from level 0 to 4 (while level 3 is non existent), we should be able to see the level 2 before loading the level 4. Is that what you mean?

@ravenfeld
Copy link
Author

ravenfeld commented Jan 4, 2022

If you only zoom in, no problem, zoom 2 stays in until you have zoom 4.
The problem is if we go from 4 to 3 and move the map. I have this problem because the tiles of zoom 2 are not called nor zoom 4, so until I search a known zoom the map will not load anything.
device-2022-01-04-074956

@p-lr
Copy link
Owner

p-lr commented Jan 4, 2022

Alright, it's clear now. FWIW, a proper way to handle missing levels (or "level gaps") is to subsample tiles from the next reachable level. The reason is: imagine you have levels 1 to 10 and levels 2 to 9 are missing. When zooming in from level 1, and when tiles from level 2 should be loaded, suddenly loading tiles from level 10 would result in loading way too many tiles (hundreds, or thousands). The result would be an out of memory error (OOM).
MapView does subsampling, but only when zooming out, and using tiles from the lowest level. Enabling subsampling for level gaps is absolutely not a trivial task, and is actually a dramatic design shift.
However, I believe it's acceptable to relax the current policy and allow for a gap of one level and no more. That would fix your use case, but I wouldn't allow for two consecutive levels to be missing as the risk of OOM is too great.

@ravenfeld
Copy link
Author

Or maybe a mapView configuration where we give the available zoom levels?
If the zoom 3 does not exist we recover the level 2. I did not understand well, you say that it is already done but why zoom 3 does not recover zoom 2 when you move the map? I may have forgotten a configuration.

@p-lr
Copy link
Owner

p-lr commented Jan 4, 2022

Or maybe a mapView configuration where we give the available zoom levels?

MapView wasn't designed for that. It's built with the assumption that there are no missing levels.
Consequently, changing how tiles are requested based on missing levels doesn't fit with the current logic. Making exceptions for a custom configuration would complicate things and I'm afraid I'm not willing to do this.
Is one missing level not enough ?

@p-lr
Copy link
Owner

p-lr commented Jan 4, 2022

Actually, as I'm thinking about it, I realized that what I suggested about tolerating one missing level would only be a workaround for zooming out. It wouldn't work when panning, as only tiles from the current level would be requested.
Well... your issue requires a major design change. Maybe one day I'll have time to do this. But in the meantime, I guess your best bet is to fill the gaps.

@ravenfeld
Copy link
Author

ok, I use OSMAnd and it handles this lack concern well, I'll look at how they did it. Because for the moment I can't modify the lib to have a good return.

@ravenfeld
Copy link
Author

ravenfeld commented Jan 4, 2022

If you have any idea how to get the tile from the level out I'm interested, I've done some things that don't work now and I don't have much idea.
Or if you know a lib that can meet my needs.
Because to recover all the zoom while some are just zoom of the lower level it is a pity and so I did not recover all to not have a huge database.

@p-lr
Copy link
Owner

p-lr commented Jan 4, 2022

Imagine you have missing level n, but you have level n + 1. Each tile from level n is made of 4 tiles of level n + 1 which form a square. If tiles are 256 px wide, the square is 512 px wide. Then, the square is subsampled to make a tile of 256 px wide.
It can be done iteratively. You can make level n from n+1, then level n-1 from level n.

Alternatively, if you start from a huge image, you can tile it and generate all intermediary levels using libvips. See this tutorial.

@ravenfeld
Copy link
Author

I understood the principle but when I ask for zoom 3 col 5 row 4 I can't find the values for zoom 2 of col and row

@ravenfeld
Copy link
Author

I don't see how getting the lower zoom will make a memory error since the image is smaller.

@p-lr
Copy link
Owner

p-lr commented Jan 4, 2022

A tile from level n, with row i and col j, noted Tile(n, i, j) corresponds to 4 tiles at level n + 1:
Tile(n+1, 2i, 2j)
Tile(n+1, 2i + 1, 2j)
Tile(n+1, 2i, 2j + 1)
Tile(n+1, 2i + 1, 2j + 1)

I don't see how getting the lower zoom will make a memory error since the image is smaller.

MapView does not look for lower levels, be cause it wasn't designed for missing levels.

@ravenfeld
Copy link
Author

In the zoom direction I understood well but from zoom 3 to know the zoom 2 tile I can not.
I understand that it doesn't work now, I'm trying to modify it so that it works.

@p-lr
Copy link
Owner

p-lr commented Jan 4, 2022

Well the formula is all there. You have to treat tiles from level n+1 four by four, starting from the upper left corner, and generate tiles for the lower level.

@ravenfeld
Copy link
Author

We don't understand each other, I try to do this.
Tile(n+1, 2i, 2j) => Tile(n, i, j)
Tile(n+1, 2i + 1, 2j) => Tile(n, i, j)
Tile(n+1, 2i, 2j + 1) => Tile(n, i, j)
Tile(n+1, 2i + 1, 2j + 1) => Tile(n, i, j)

@p-lr
Copy link
Owner

p-lr commented Jan 4, 2022

You got it. Start from the upper left corner of level n+1:

Tile(n, 0, 0):

  • Tile(n+1, 0, 0)
  • Tile(n+1, 1, 0)
  • Tile(n+1, 0, 1)
  • Tile(n+1, 1, 1)
    => Fuse those 4 tiles into one

Tile(n, 0, 1):

  • Tile(n+1, 0, 2)
  • Tile(n+1, 1, 2)
  • Tile(n+1, 0, 3)
  • Tile(n+1, 1, 3)
    => Fuse those 4 tiles into one

And so on.

@ravenfeld
Copy link
Author

Je passe en francais, nous nous sommes pas compris. je ne veux pas trouver les tuiles du zoom plus precis mais du zoom inférieur.
Mon idée c'est que si j'ai pas le zoom precis j'affiche le zoom moins precis. Du coup quand le woker demande la tuile zoom 3 si je la trouve pas je demande la tuile zoom 2 pas la tuile zoom 4 qui comme tu l'as dit demandera beaucoup de ressource.

@p-lr
Copy link
Owner

p-lr commented Jan 4, 2022

Ce n'est malheureusement pas possible avec MapView, à moins de modifier la lib en profondeur. Le plus simple, quand on a la main sur les données, est de générer les niveaux manquants avec les formules au dessus.

@ravenfeld
Copy link
Author

Thanks a lot, I'll see if I can do something. If not, I'll see if there are other libs.

@p-lr p-lr closed this as completed Feb 10, 2022
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

No branches or pull requests

2 participants