Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Tile coverage updates #9284

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified benchmark/fixtures/api/cache.db
Binary file not shown.
2 changes: 1 addition & 1 deletion include/mbgl/util/constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ constexpr double EARTH_RADIUS_M = 6378137;
constexpr double LATITUDE_MAX = 85.051128779806604;
constexpr double LONGITUDE_MAX = 180;
constexpr double DEGREES_MAX = 360;
constexpr double PITCH_MAX = M_PI / 3;
constexpr double PITCH_MAX = 1.39626; // ~80 degrees.
constexpr double MIN_ZOOM = 0.0;
constexpr double MAX_ZOOM = 25.5;
constexpr float MIN_ZOOM_F = MIN_ZOOM;
Expand Down
69 changes: 42 additions & 27 deletions src/mbgl/util/tile_cover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,22 +80,28 @@ std::vector<UnwrappedTileID> tileCover(const Point<double>& tl,
const Point<double>& br,
const Point<double>& bl,
const Point<double>& c,
int32_t z) {
const int32_t tiles = 1 << z;
uint8_t zoom) {
const int32_t maxTilesPerAxis = 1 << zoom;

struct ID {
struct CoverID {
int32_t x, y;
double sqDist;
};

std::vector<ID> t;
std::vector<CoverID> coverIDs;
// Simple bbox for pre-reserving coverIDs elements.
const auto maxX = util::max(tl.x, tr.x, br.x, bl.x);
const auto minX = util::min(tl.x, tr.x, br.x, bl.x);
const auto maxY = util::max(tl.y, tr.x, br.x, bl.x);
const auto minY = util::min(tl.y, tr.y, br.y, bl.y);
coverIDs.reserve(util::clamp(0lu, size_t((maxX - minX) * (maxY - minY)), std::numeric_limits<size_t>::max()));

auto scanLine = [&](int32_t x0, int32_t x1, int32_t y) {
int32_t x;
if (y >= 0 && y <= tiles) {
if (y >= 0 && y <= maxTilesPerAxis) {
for (x = x0; x < x1; ++x) {
const auto dx = x + 0.5 - c.x, dy = y + 0.5 - c.y;
t.emplace_back(ID{ x, y, dx * dx + dy * dy });
coverIDs.emplace_back(CoverID { x, y, dx * dx + dy * dy });
}
}
};
Expand All @@ -104,22 +110,23 @@ std::vector<UnwrappedTileID> tileCover(const Point<double>& tl,
// \---+
// | \ |
// +---\.
scanTriangle(tl, tr, br, 0, tiles, scanLine);
scanTriangle(br, bl, tl, 0, tiles, scanLine);
scanTriangle(tl, tr, br, 0, maxTilesPerAxis, scanLine);
scanTriangle(br, bl, tl, 0, maxTilesPerAxis, scanLine);

// Sort first by distance, then by x/y.
std::sort(t.begin(), t.end(), [](const ID& a, const ID& b) {
std::sort(coverIDs.begin(), coverIDs.end(), [](const CoverID& a, const CoverID& b) {
return std::tie(a.sqDist, a.x, a.y) < std::tie(b.sqDist, b.x, b.y);
});

// Erase duplicate tile IDs (they typically occur at the common side of both triangles).
t.erase(std::unique(t.begin(), t.end(), [](const ID& a, const ID& b) {
coverIDs.erase(std::unique(coverIDs.begin(), coverIDs.end(), [](const CoverID& a, const CoverID& b) {
return a.x == b.x && a.y == b.y;
}), t.end());
}), coverIDs.end());

std::vector<UnwrappedTileID> result;
for (const auto& id : t) {
result.emplace_back(z, id.x, id.y);
result.reserve(coverIDs.size());
for (const auto& coverID : coverIDs) {
result.emplace_back(zoom, coverID.x, coverID.y);
}
return result;
}
Expand All @@ -135,7 +142,7 @@ int32_t coveringZoomLevel(double zoom, SourceType type, uint16_t size) {
}
}

std::vector<UnwrappedTileID> tileCover(const LatLngBounds& bounds_, int32_t z) {
std::vector<UnwrappedTileID> tileCover(const LatLngBounds& bounds_, uint8_t zoom) {
if (bounds_.isEmpty() ||
bounds_.south() > util::LATITUDE_MAX ||
bounds_.north() < -util::LATITUDE_MAX) {
Expand All @@ -147,26 +154,34 @@ std::vector<UnwrappedTileID> tileCover(const LatLngBounds& bounds_, int32_t z) {
{ std::min(bounds_.north(), util::LATITUDE_MAX), bounds_.east() });

return tileCover(
TileCoordinate::fromLatLng(z, bounds.northwest()).p,
TileCoordinate::fromLatLng(z, bounds.northeast()).p,
TileCoordinate::fromLatLng(z, bounds.southeast()).p,
TileCoordinate::fromLatLng(z, bounds.southwest()).p,
TileCoordinate::fromLatLng(z, bounds.center()).p,
z);
TileCoordinate::fromLatLng(zoom, bounds.northwest()).p,
TileCoordinate::fromLatLng(zoom, bounds.northeast()).p,
TileCoordinate::fromLatLng(zoom, bounds.southeast()).p,
TileCoordinate::fromLatLng(zoom, bounds.southwest()).p,
TileCoordinate::fromLatLng(zoom, bounds.center()).p,
zoom);
}

std::vector<UnwrappedTileID> tileCover(const TransformState& state, int32_t z) {
std::vector<UnwrappedTileID> tileCover(const TransformState& state, uint8_t zoom) {
assert(state.valid());

const double w = state.getSize().width;
const double h = state.getSize().height;

// Limit tile coverage when pitch >= 60 degrees (M_PI / 3).
const double clampedH = [&]() {
const double clampedPitch = state.getPitch() - M_PI / 3;
return clampedPitch <= 0 ? h : h - (h * std::sin(clampedPitch));
}();

// top-left, top-right, bottom-right, bottom-left, center
return tileCover(
TileCoordinate::fromScreenCoordinate(state, z, { 0, 0 }).p,
TileCoordinate::fromScreenCoordinate(state, z, { w, 0 }).p,
TileCoordinate::fromScreenCoordinate(state, z, { w, h }).p,
TileCoordinate::fromScreenCoordinate(state, z, { 0, h }).p,
TileCoordinate::fromScreenCoordinate(state, z, { w/2, h/2 }).p,
z);
TileCoordinate::fromScreenCoordinate(state, zoom, { 0, 0 }).p,
TileCoordinate::fromScreenCoordinate(state, zoom, { w, 0 }).p,
TileCoordinate::fromScreenCoordinate(state, zoom, { w, clampedH }).p,
TileCoordinate::fromScreenCoordinate(state, zoom, { 0, clampedH }).p,
TileCoordinate::fromScreenCoordinate(state, zoom, { w/2, h/2 }).p,
zoom);
}

} // namespace util
Expand Down
4 changes: 2 additions & 2 deletions src/mbgl/util/tile_cover.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ namespace util {

int32_t coveringZoomLevel(double z, SourceType type, uint16_t tileSize);

std::vector<UnwrappedTileID> tileCover(const TransformState&, int32_t z);
std::vector<UnwrappedTileID> tileCover(const LatLngBounds&, int32_t z);
std::vector<UnwrappedTileID> tileCover(const TransformState&, uint8_t zoom);
std::vector<UnwrappedTileID> tileCover(const LatLngBounds&, uint8_t zoom);

} // namespace util
} // namespace mbgl