-
-
Notifications
You must be signed in to change notification settings - Fork 362
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
Improve floating point issues with tile/lat conversion #5091
Improve floating point issues with tile/lat conversion #5091
Conversation
I lost track of the issue. What issues does it cause exactly if converting forth and back between bbox and tile position does not work in 100% of cases? Also, where (and why) is converting forth and back between bbox and tile position necessary? |
This mainly affects the cache, which uses tiles internally but bboxes otherwise StreetComplete/app/src/main/java/de/westnordost/streetcomplete/util/SpatialCache.kt Lines 77 to 93 in 5cc6506
So depending on your latitude, you may get worse performance than expected. |
Ah, I see. Hm well, I do not understand how nextDown / nextUp solves things. This formula,
should be 100% correct minus the floating point imprecision. So, subtracting or adding a close to infinite amount from or to it should actually make it less correct. Actually, I didn't know that |
Some comparison with higher precision numbers (80 bit using python / numpy):
When doing this, with lat close to 180 there are issues in: val p = LatLon(latitude=81.07546376846332, longitude=179.99321275770234)
val tile = p.enclosingTilePos(15)
val bbox = tile.asBoundingBox(15)
val r = bbox.enclosingTilesRect(15)
|
Hm, a little difficult when the communication happens with such delays. Then you have to "reinfuchsen" in the matter each time you respond anew. Anyway, as you see I am reluctant to merge a deviation to the standard formula that everybody uses as this is obviously the mathematically correct one. You have run a lot of tests and you came to the conclusion that it is more precise in edge cases, but I am missing the "why" here.
How can there be issues with So, I would really like to replace the |
Sorry, finding a good way to compare with higher precision numbers took a while, and I had some other things to do I gave higher priority.
I honestly don't know. My initial idea was that there is some precision issue amplifying towards one direction in
No, with 1e-12 it works normally
I didn't yet investigate what causes the |
The reason is in |
Where does 179.99999999999997 come from? |
That's one of the longitudes from |
Anyway, I'm considering whether properly investiating all this is really worth more time... maybe I'll just close the PR |
In another test, Looking again into the topic and why it is necessary to calculate close to the floating point precision, the only point where this is important is for the So I wonder if the more stable solution wouldn't be to drop the - val (completelyContainedTiles, incompleteTiles) =
- tiles.partition { it.asBoundingBox(tileZoom).isCompletelyInside(bbox) }
+ val (completelyContainedTiles, incompleteTiles) =
+ tiles.partition { it.asBoundingBox(tileZoom).toOsmPrecision().isCompletelyInside(bbox) } ...where
becomes
Consideration: The gaps between the bounding boxes (up to 10cm IIRC) shrunk this way do not matter for application in the OSM world, because 7 digits is already the maximum precision, i.e. no elements would be outside any bounding box. At the same time, the bounding boxes thus are so well within tiles (compared to what would be near floating point precision), that imprecision through calculations on floating points should not matter anymore. |
I agree, then we don't have to care about precision issues. |
This greatly reduces the number of
LatLon
s whereStreetComplete/app/src/test/java/de/westnordost/streetcomplete/data/download/tiles/TilesRectTest.kt
Line 13 in 5cc6506
It's a draft because the change to
tile2lat
causes the test forp(0.0, 0.0)
to fail. This is some sort of "special" point that's used in many other tests, and thus I think it really needs to work.So far the only way I found it to work for
p(0.0, 0.0)
is treatingy == numTiles(zoom) / 2
as a special case intile2lat
, though this looks a bit ugly.Slightly modified
convert bbox to tiles rect and back results in same bbox
using 1 million random coordinates (with lat limited to range from -85 to 85) fail count:lat2tile
nextUp
: ca 53ktile2lat
nextDown
: ca 9200tile2lat
nextDown
and moving/ PI
: ca 6700