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

Grid: Unpredictable interactions between ToNative and FromNative #127

Open
jchamberlain opened this issue Sep 12, 2023 · 2 comments
Open

Comments

@jchamberlain
Copy link

jchamberlain commented Sep 12, 2023

Expected

Grid.ToNative() should return the top-left point of the given tile:

grid, _ := slippy.NewGrid(3857)
tile := slippy.NewTile(5, 0, 0)
point, _ := grid.ToNative(tile)
fmt.Println(point) // [-2.003750834e+07 2.003750834e+07]

Grid.FromNative() should return the tile corresponding to a top-left point:

grid, _ := slippy.NewGrid(3857)
tile, _ := grid.FromNative(5, geom.Point{-2.003750834e7, 2.003750834e7})
fmt.Println(tile) // &{5 0 0}

FromNative() and ToNative() should be able to reverse each other predictably. That is, FromNative(ToNative(x)) == x.

Problem

The above does not hold for all coordinates. In the following example, 5,3,5 becomes 5,3,4:

grid, _ := NewGrid(3857)
tile1 := NewTile(5, 3, 5)
point, _ := grid.ToNative(tile1)
tile2, _ := grid.FromNative(5, point)
fmt.Println(tile2) // &{5 3 4}

x=3 and y=5 seems to be buggy at multiple zooms (try 6,3,5, 7,3,5, and 8,3,5)

Impact

Whatever is causing this problem seems to make slippy.RangeFamilyAt() unpredictable as well, as it relies on ToNative() and FromNative(). When updating Tegola to use the latest geom (go-spatial/tegola#952), I couldn't get RangeFamilyAt() to work and had to copy in the old version which does not make use of these functions.

Note: it's entirely possible this is related to me using an M1 Mac. I see slightly smaller floats generated on a regular basis, so maybe someone could try this on amd64?

@gdey
Copy link
Member

gdey commented Sep 12, 2023

Converting to/from an SRID is a lossy action; it is not expected to be a perfect transformation. Usually, you want to reduce the number of transforms you do.

@jchamberlain
Copy link
Author

jchamberlain commented Sep 12, 2023

That makes sense. In which case, RangeFamilyAt() should be completely reverted as it relies on converting back and forth between zoom ranges, and is thus unpredictable.

I'm also not 100% clear if converting to/from an SRID is what's happening here. My understanding was that it's converting between slippy tile names and Web Mercator units. Shouldn't you be able to go back and forth between those predictably? Put another way, I assume this would only happen if ToNative() is returning a point that FromNative() considers to be outside of the tile. That feels intuitively like something which should be able to be reconciled.

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