Implement distance-based tile LOD (#4057)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bart Louwers <bart@emeel.net>
This commit is contained in:
Nathan Olson
2026-02-21 03:38:10 -08:00
committed by GitHub
parent 8e0dc86956
commit 7fe58506c4
45 changed files with 650 additions and 86 deletions

View File

@@ -10,6 +10,8 @@
using namespace mbgl;
const Range<uint8_t> zoomRange(0, 14);
TEST(TileCover, Empty) {
EXPECT_EQ((std::vector<UnwrappedTileID>{}), util::tileCover(LatLngBounds::empty(), 0));
}
@@ -44,7 +46,12 @@ TEST(TileCover, Pitch) {
.withPitch(40.0));
EXPECT_EQ((std::vector<OverscaledTileID>{{2, 1, 1}, {2, 2, 1}, {2, 1, 2}, {2, 2, 2}}),
util::tileCover({transform.getState()}, 2));
util::tileCover({transform.getState()}, 2, zoomRange));
util::TileCoverParameters params{transform.getState()};
params.tileLodMode = TileLodMode::Distance;
EXPECT_EQ((std::vector<OverscaledTileID>{{2, 1, 2}, {2, 2, 2}, {2, 1, 1}, {2, 2, 1}}),
util::tileCover(params, 2, zoomRange));
}
TEST(TileCover, PitchIssue15442) {
@@ -62,7 +69,47 @@ TEST(TileCover, PitchIssue15442) {
EXPECT_EQ((std::vector<OverscaledTileID>{
{2, 3, 1}, {2, 2, 1}, {2, 3, 0}, {2, 2, 0}, {2, 1, {2, 0, 0}}, {2, 1, {2, 1, 0}}}),
util::tileCover({transform.getState()}, 2));
util::tileCover({transform.getState()}, 2, zoomRange));
util::TileCoverParameters params{transform.getState()};
params.tileLodMode = TileLodMode::Distance;
EXPECT_EQ((std::vector<OverscaledTileID>{
{2, 2, 1}, {2, 3, 1}, {2, 2, 0}, {2, 3, 0}, {2, 1, {2, 0, 0}}, {2, 1, {2, 1, 0}}}),
util::tileCover(params, 2, zoomRange));
}
TEST(TileCover, HighPitch) {
Transform transform;
transform.resize({512, 512});
// slightly offset center so that tile order is better defined
transform.jumpTo(CameraOptions()
.withCenter(LatLng{
0.1,
-0.1,
})
.withZoom(2.0)
.withBearing(5.0)
.withPitch(60.0));
util::TileCoverParameters params{transform.getState()};
params.tileLodPitchThreshold = 0.0;
params.tileLodMinRadius = 1.0;
EXPECT_EQ(
(std::vector<OverscaledTileID>{{2, 1, 1}, {2, 2, 1}, {2, 1, 2}, {2, 2, 2}, {2, 1, 0}, {2, 2, 0}, {2, 3, 0}}),
util::tileCover(params, 2, zoomRange));
params.tileLodMode = TileLodMode::Distance;
EXPECT_EQ((std::vector<OverscaledTileID>{{2, 1, 1},
{2, 2, 1},
{3, 3, 4},
{3, 3, 5},
{2, 1, 0},
{2, 2, 0},
{3, 4, 4},
{2, 3, 0},
{3, 4, 5},
{3, 5, 4}}),
util::tileCover(params, 2, zoomRange));
}
TEST(TileCover, PitchOverAllowedByContentInsets) {
@@ -79,7 +126,12 @@ TEST(TileCover, PitchOverAllowedByContentInsets) {
EXPECT_LE(transform.getPitch() + 0.001, util::deg2rad(60));
EXPECT_EQ((std::vector<OverscaledTileID>{{3, 4, 3}, {3, 3, 3}, {3, 4, 4}, {3, 3, 4}}),
util::tileCover({transform.getState()}, 3));
util::tileCover({transform.getState()}, 3, zoomRange));
util::TileCoverParameters params{transform.getState()};
params.tileLodMode = TileLodMode::Distance;
EXPECT_EQ((std::vector<OverscaledTileID>{{3, 3, 4}, {3, 3, 3}, {3, 4, 4}, {3, 4, 3}}),
util::tileCover(params, 3, zoomRange));
}
TEST(TileCover, PitchWithLargerResultSet) {
@@ -95,7 +147,7 @@ TEST(TileCover, PitchWithLargerResultSet) {
.withBearing(-142.2630000003529176)
.withPitch(60.0));
auto cover = util::tileCover({.transformState = transform.getState()}, 5);
auto cover = util::tileCover({.transformState = transform.getState()}, 5, zoomRange);
// Returned vector has above 100 elements, we check first 16 as there is a
// plan to return lower LOD for distant tiles.
EXPECT_EQ((std::vector<OverscaledTileID>{{5, 15, 16},
@@ -147,7 +199,13 @@ TEST(TileCover, CoordinatesAreUnwrapped) {
EXPECT_EQ(
(std::vector<OverscaledTileID>{{1, 0, {1, 1, 0}}, {1, 1, {1, 0, 0}}, {1, 0, {1, 1, 1}}, {1, 1, {1, 0, 1}}}),
util::tileCover({transform.getState()}, 1));
util::tileCover({transform.getState()}, 1, zoomRange));
util::TileCoverParameters params{transform.getState()};
params.tileLodMode = TileLodMode::Distance;
EXPECT_EQ(
(std::vector<OverscaledTileID>{{1, 0, {1, 1, 0}}, {1, 1, {1, 0, 0}}, {1, 0, {1, 1, 1}}, {1, 1, {1, 0, 1}}}),
util::tileCover(params, 1, zoomRange));
}
TEST(TileCover, DifferentOverscaledZ) {
@@ -164,7 +222,13 @@ TEST(TileCover, DifferentOverscaledZ) {
EXPECT_EQ(
(std::vector<OverscaledTileID>{{3, 0, {2, 1, 1}}, {3, 0, {2, 2, 1}}, {3, 0, {2, 1, 2}}, {3, 0, {2, 2, 2}}}),
util::tileCover({transform.getState()}, 2, 3));
util::tileCover({transform.getState()}, 2, zoomRange, 3));
util::TileCoverParameters params{transform.getState()};
params.tileLodMode = TileLodMode::Distance;
EXPECT_EQ(
(std::vector<OverscaledTileID>{{3, 0, {2, 1, 1}}, {3, 0, {2, 2, 1}}, {3, 0, {2, 1, 2}}, {3, 0, {2, 2, 2}}}),
util::tileCover(params, 2, zoomRange, 3));
}
TEST(TileCover, DifferentOverscaledZWithPitch) {
@@ -176,7 +240,7 @@ TEST(TileCover, DifferentOverscaledZWithPitch) {
-10.0,
})
.withZoom(3.5)
.withPitch(60));
.withPitch(61));
EXPECT_EQ((std::vector<OverscaledTileID>{{5, 0, {3, 3, 3}},
{5, 0, {3, 4, 3}},
@@ -185,7 +249,18 @@ TEST(TileCover, DifferentOverscaledZWithPitch) {
{5, 0, {3, 3, 1}},
{5, 0, {3, 4, 1}},
{5, 0, {3, 2, 1}}}),
util::tileCover({transform.getState()}, 3, 5));
util::tileCover({transform.getState()}, 3, zoomRange, 5));
util::TileCoverParameters params{transform.getState()};
params.tileLodMode = TileLodMode::Distance;
EXPECT_EQ((std::vector<OverscaledTileID>{{5, 0, {3, 3, 3}},
{5, 0, {3, 4, 3}},
{5, 0, {3, 3, 2}},
{5, 0, {3, 4, 2}},
{5, 0, {3, 3, 1}},
{5, 0, {3, 4, 1}},
{5, 0, {3, 2, 1}}}),
util::tileCover(params, 3, zoomRange, 5));
}
TEST(TileCover, DifferentOverscaledZWrapped) {
@@ -200,7 +275,13 @@ TEST(TileCover, DifferentOverscaledZWrapped) {
EXPECT_EQ(
(std::vector<OverscaledTileID>{{2, 0, {1, 1, 0}}, {2, 1, {1, 0, 0}}, {2, 0, {1, 1, 1}}, {2, 1, {1, 0, 1}}}),
util::tileCover({transform.getState()}, 1, 2));
util::tileCover({transform.getState()}, 1, zoomRange, 2));
util::TileCoverParameters params{transform.getState()};
params.tileLodMode = TileLodMode::Distance;
EXPECT_EQ(
(std::vector<OverscaledTileID>{{2, 0, {1, 1, 0}}, {2, 1, {1, 0, 0}}, {2, 0, {1, 1, 1}}, {2, 1, {1, 0, 1}}}),
util::tileCover(params, 1, zoomRange, 2));
}
TEST(TileCover, FlippedY) {
@@ -215,7 +296,12 @@ TEST(TileCover, FlippedY) {
.withZoom(1.0));
EXPECT_EQ((std::vector<OverscaledTileID>{{1, 0, 0}, {1, 1, 0}, {1, 0, 1}, {1, 1, 1}}),
util::tileCover({transform.getState()}, 1));
util::tileCover({transform.getState()}, 1, zoomRange));
util::TileCoverParameters params{transform.getState()};
params.tileLodMode = TileLodMode::Distance;
EXPECT_EQ((std::vector<OverscaledTileID>{{1, 0, 0}, {1, 1, 0}, {1, 0, 1}, {1, 1, 1}}),
util::tileCover(params, 1, zoomRange));
}
TEST(TileCover, FlippedYPitch) {
@@ -232,7 +318,12 @@ TEST(TileCover, FlippedYPitch) {
.withPitch(40.0));
EXPECT_EQ((std::vector<OverscaledTileID>{{2, 1, 1}, {2, 2, 1}, {2, 1, 2}, {2, 2, 2}}),
util::tileCover({transform.getState()}, 2));
util::tileCover({transform.getState()}, 2, zoomRange));
util::TileCoverParameters params{transform.getState()};
params.tileLodMode = TileLodMode::Distance;
EXPECT_EQ((std::vector<OverscaledTileID>{{2, 1, 2}, {2, 2, 2}, {2, 1, 1}, {2, 2, 1}}),
util::tileCover(params, 2, zoomRange));
}
TEST(TileCover, FlippedYHelsinki) {
@@ -247,7 +338,12 @@ TEST(TileCover, FlippedYHelsinki) {
.withZoom(11.447425));
EXPECT_EQ((std::vector<OverscaledTileID>{{11, 1165, 592}, {11, 1166, 592}, {11, 1165, 593}, {11, 1166, 593}}),
util::tileCover({transform.getState()}, 11));
util::tileCover({transform.getState()}, 11, zoomRange));
util::TileCoverParameters params{transform.getState()};
params.tileLodMode = TileLodMode::Distance;
EXPECT_EQ((std::vector<OverscaledTileID>{{11, 1165, 592}, {11, 1166, 592}, {11, 1165, 593}, {11, 1166, 593}}),
util::tileCover(params, 11, zoomRange));
}
TEST(TileCoverStream, Arctic) {