-
-
Notifications
You must be signed in to change notification settings - Fork 216
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
Fix bbox to xyz roundtrip computation #1059
Conversation
@sharkAndshark please take a look at this function - i think you may know more about it. See if you know how to fix it? |
I'm trying to understand what's the bug here. |
@sharkAndshark this test fails, but I was expecting it should succeed. See https://github.com/maplibre/martin/actions/runs/7155799338/job/19484815026 :
The Y coordinate gets decoded as an inverse. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really want to introduce a new tms concept into all this? I was hoping we can keep the whole system using the same xyz, and only the mbtiles crate to know to invert it last minute.
Agree. Use TMS only when it's |
2c5c2cd
to
103704c
Compare
There are several ways to implement the "tile ID" concept:
|
P.S. We really should not implement this ourselves. Instead, we should rely on the other crates as mentioned in #1059 (comment) |
I think the first two should be done together. As far as I can see, most code is already xyz, so should be minimal changes. The 3rd is optional, but it might be easier to just use tile grid directly from the start, and not bother with fixing the first two? Not sure. |
Before to do anything else, I think we need to talk about this: assert_relative_eq!(bbox[0], -168.74999999999955, epsilon = f64::EPSILON * 2.0);
assert_relative_eq!(bbox[1], 74.01954331150218, epsilon = f64::EPSILON * 2.0);
assert_relative_eq!(bbox[2], -146.2499999999996, epsilon = f64::EPSILON * 2.0);
assert_relative_eq!(bbox[3], 81.09321385260832, epsilon = f64::EPSILON * 2.0);
// Fixme: These are totally wrong
let xyz = bbox_to_xyz(bbox[0], bbox[1], bbox[2], bbox[3], 5);
assert_eq!(xyz, (1, 3, 2, 5)); assertion `left == right` failed
left: (1, 3, 3, 6)
right: (1, 3, 2, 5) It's difficult to handle when it's corner of tile bbox. Should we introduce a tolerance here? I'm still thinking of it. Any help? @nyurik |
Thanks! This is still much better than before, and I am actually Ok with it being "slightly" different - as this is a floating point rounding error. I think our testing should be like this:
let xyz = bbox_to_xyz(bbox[0], bbox[1], bbox[2], bbox[3], 5);
// these numbers might be slightly wrong?
assert!(xyz.left == 0 || xyz.left == 1);
assert!(xyz.top == 2 || xyz.top == 3);
assert!(xyz.right == 2 || xyz.right == 3);
assert!(xyz.bottom == 5 || xyz.bottom == 6); |
b751d32
to
a94b489
Compare
@nyurik Do you actually mean buffered by? Then the test code would be like: // For left top corner
assert!(tile_col == some_value || tile_col == some_value + 1)
assert!(tile_row == some_value || tile_row == some_value - 1) // For right down corner
assert!(tile_col == some_value || tile_col == some_value +1)
assert!(tile_row == some_value || tile_row == some_value + 1) |
martin-tile-utils/src/lib.rs
Outdated
let max_value = (1_u32 << zoom) - 1; | ||
(x.min(max_value), y.min(max_value)) | ||
pub fn tile_index(lon: f64, lat: f64, zoom: u8) -> (u64, u64) { | ||
let tms = tms().lookup("WebMercatorQuad").unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to move tms creation into static lazy init block. See https://docs.rs/lazy_static/latest/lazy_static/ - it is already being used for some other dependencies, so might as well use that too. This way we won't do it on each call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use OnceLock instead, is it Ok?
I tried many times but the lazy_static
crate didn't work on my computer. Maybe it's because my rust version( I've already run rustup update) I'm not sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
im ok with the oncelock (eventually everything will migrate to the core i think), but you do realize you are already using lazy_static as part of insta, console, and other crates which are used in martin?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBH I didn't realized... 😂😂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still a lot to learn.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, seems that tile-grid crate used OnceCell internall.
/// Global registry of tile matrix sets
pub fn tms() -> &'static TileMatrixSets {
static TMS: OnceCell<TileMatrixSets> = OnceCell::new();
&TMS.get_or_init(|| {
let mut sets = TileMatrixSets::new();
let tms = vec![
#[cfg(feature = "projtransform")]
include_str!("../data/CanadianNAD83_LCC.json"),
//include_str!("../data/CDB1GlobalGrid.json"), // Error("missing field `coalesc`", line: 19, column: 67)
#[cfg(feature = "projtransform")]
include_str!("../data/EuropeanETRS89_LAEAQuad.json"),
//include_str!("../data/GNOSISGlobalGrid.json"), // Error("missing field `coalesc`", line: 31, column: 66)
#[cfg(feature = "projtransform")]
include_str!("../data/UPSAntarcticWGS84Quad.json"),
#[cfg(feature = "projtransform")]
include_str!("../data/UPSArcticWGS84Quad.json"),
#[cfg(feature = "projtransform")]
include_str!("../data/UTM31WGS84Quad.json"),
include_str!("../data/WebMercatorQuad.json"),
include_str!("../data/WGS1984Quad.json"),
//include_str!("../data/WorldCRS84Quad.json"), // conflicts with WGS1984Quad
include_str!("../data/WorldMercatorWGS84Quad.json"),
]
.into_iter()
.map(|data| TileMatrixSet::from_json(&data).unwrap())
.collect::<Vec<_>>();
sets.register(tms, false).unwrap();
// user_tms_dir = os.environ.get("TILEMATRIXSET_DIRECTORY", None)
// if user_tms_dir:
// tms_paths.extend(list(pathlib.Path(user_tms_dir).glob("*.json")))
sets
})
}
c913956
to
18f73cb
Compare
martin-tile-utils/src/lib.rs
Outdated
let max_value = (1_u32 << zoom) - 1; | ||
(x.min(max_value), y.min(max_value)) | ||
pub fn tile_index(lon: f64, lat: f64, zoom: u8) -> (u64, u64) { | ||
let tms = tms().lookup("WebMercatorQuad").unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use OnceLock instead, is it Ok?
I tried many times but the lazy_static
crate didn't work on my computer. Maybe it's because my rust version( I've already run rustup update) I'm not sure.
will review & merge shortly, thx for all the hard work! |
thanks for fixing this!!! |
@sharkAndshark sadly, this solution still has some weird bug, and does not fully solve general use case. It seems the Notice that beyond z24, all values are identical #[test]
fn test_box() {
fn tst(left: f64, bottom: f64, right: f64, top: f64, zoom: u8) -> String {
let (x0, y0, x1, y1) = bbox_to_xyz(left, bottom, right, top, zoom);
format!("({x0}, {y0}, {x1}, {y1})")
}
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 0), @"(0, 0, 0, 0)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 1), @"(0, 1, 0, 1)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 2), @"(0, 3, 0, 3)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 3), @"(0, 7, 0, 7)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 4), @"(0, 14, 1, 15)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 5), @"(0, 29, 2, 31)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 6), @"(0, 58, 5, 63)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 7), @"(0, 116, 11, 126)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 8), @"(0, 233, 23, 253)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 9), @"(0, 466, 47, 507)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 10), @"(1, 933, 94, 1014)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 11), @"(3, 1866, 188, 2029)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 12), @"(6, 3732, 377, 4059)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 13), @"(12, 7465, 755, 8119)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 14), @"(25, 14931, 1510, 16239)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 15), @"(51, 29863, 3020, 32479)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 16), @"(102, 59727, 6041, 64958)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 17), @"(204, 119455, 12083, 129917)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 18), @"(409, 238911, 24166, 259834)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 19), @"(819, 477823, 48332, 519669)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 20), @"(1638, 955647, 96665, 1039339)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 21), @"(3276, 1911295, 193331, 2078678)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 22), @"(6553, 3822590, 386662, 4157356)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 23), @"(13107, 7645181, 773324, 8314713)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 24), @"(26214, 15290363, 1546649, 16629427)");
// All these are incorrect
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 25), @"(33554431, 33554431, 33554431, 33554431)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 26), @"(67108863, 67108863, 67108863, 67108863)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 27), @"(134217727, 134217727, 134217727, 134217727)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 28), @"(268435455, 268435455, 268435455, 268435455)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 29), @"(536870911, 536870911, 536870911, 536870911)");
assert_snapshot!(tst(-179.43749999999955,-84.76987877980656,-146.8124999999996,-81.37446385260833, 30), @"(1073741823, 1073741823, 1073741823, 1073741823)");
} |
Weired. I'm debuging. |
Add
tile-grid
as a dependency to use its webmercator tile math.