use a custom struct for Tile IDs

This commit is contained in:
Konstantin Käfer
2014-03-12 16:42:37 +01:00
parent 8fd4d855d5
commit 86e6e6bed8
7 changed files with 53 additions and 32 deletions

View File

@@ -2,11 +2,12 @@
#define LLMR_MAP_COVERAGE
#include <llmr/util/vec.hpp>
#include <llmr/map/tile.hpp>
#include <forward_list>
namespace llmr {
std::forward_list<vec3<int32_t>> covering_tiles(int32_t zoom, const box& points);
std::forward_list<Tile::ID> covering_tiles(int32_t zoom, const box& points);
}

View File

@@ -14,16 +14,32 @@ class TileData;
class Tile : private util::noncopyable {
public:
typedef vec3<int32_t> ID;
struct ID {
int8_t z = 0;
int32_t x = 0, y = 0;
inline ID(uint8_t z, uint32_t x, uint32_t y)
: z(z), x(x), y(y) {
}
inline operator uint64_t() const {
uint32_t dim = 1 << z;
return ((dim * y + x) * 32) + z;
}
inline bool operator==(const ID& rhs) const {
return z == rhs.z && x == rhs.x && y == rhs.y;
}
ID parent(int32_t z) const;
void normalize();
ID normalized() const;
std::forward_list<ID> children(int32_t z) const;
};
public:
Tile(const ID& id);
static ID parent(const ID& id, int32_t z);
static ID normalize(const ID& id);
static std::forward_list<ID> children(const ID& id, int32_t z);
public:
const Tile::ID id;
uint8_t clip_id;

View File

@@ -5,6 +5,7 @@
#include <llmr/util/mat4.hpp>
#include <llmr/util/animation.hpp>
#include <llmr/util/noncopyable.hpp>
#include <llmr/map/tile.hpp>
#include <forward_list>
@@ -34,7 +35,7 @@ public:
void setLonLatZoom(double lon, double lat, double zoom, double duration = 0);
// Getters
void matrixFor(mat4& matrix, const vec3<int32_t>& id) const;
void matrixFor(mat4& matrix, const Tile::ID& id) const;
float getZoom() const;
int32_t getIntegerZoom() const;
double getScale() const;

View File

@@ -64,15 +64,15 @@ void _scanTriangle(const llmr::vec2<double> a, const llmr::vec2<double> b, const
if (bc.dy) _scanSpans(ca, bc, ymin, ymax, scanLine);
}
std::forward_list<llmr::vec3<int32_t>> llmr::covering_tiles(int32_t zoom, const box& points) {
std::forward_list<llmr::Tile::ID> llmr::covering_tiles(int32_t zoom, const box& points) {
int32_t dim = pow(2, zoom);
std::forward_list<vec3<int32_t>> tiles;
std::forward_list<llmr::Tile::ID> tiles;
auto scanLine = [&tiles, zoom](int32_t x0, int32_t x1, int32_t y, int32_t ymax) {
int32_t x;
if (y >= 0 && y <= ymax) {
for (x = x0; x < x1; x++) {
tiles.emplace_front(x, y, zoom);
tiles.emplace_front(zoom, x, y);
}
}
};
@@ -85,7 +85,7 @@ std::forward_list<llmr::vec3<int32_t>> llmr::covering_tiles(int32_t zoom, const
_scanTriangle(points.br, points.bl, points.tl, 0, dim, scanLine);
const vec2<double>& center = points.center;
tiles.sort([&center](const vec3<int32_t>& a, const vec3<int32_t>& b) {
tiles.sort([&center](const Tile::ID& a, const Tile::ID& b) {
// Sorts by distance from the box center
return fabs(a.x - center.x) + fabs(a.y - center.y) <
fabs(b.x - center.x) + fabs(b.y - center.y);

View File

@@ -260,7 +260,7 @@ TileData::State Map::addTile(const Tile::ID& id) {
// We couldn't find the tile in the list. Create a new one.
// Try to find the associated TileData object.
const Tile::ID normalized_id = Tile::normalize(id);
const Tile::ID normalized_id = id.normalized();
auto it = std::find_if(tile_data.begin(), tile_data.end(), [&normalized_id](const std::weak_ptr<TileData>& tile_data) {
return !tile_data.expired() && tile_data.lock()->id == normalized_id;
@@ -299,7 +299,8 @@ bool Map::findLoadedChildren(const Tile::ID& id, int32_t maxCoveringZoom, std::f
bool complete = true;
int32_t z = id.z;
auto ids = Tile::children(id, z + 1);
auto ids = id.children(z + 1);
for (const Tile::ID& child_id : ids) {
const TileData::State state = hasTile(child_id);
if (state == TileData::State::parsed) {
@@ -326,7 +327,7 @@ bool Map::findLoadedChildren(const Tile::ID& id, int32_t maxCoveringZoom, std::f
*/
bool Map::findLoadedParent(const Tile::ID& id, int32_t minCoveringZoom, std::forward_list<Tile::ID>& retain) {
for (int32_t z = id.z - 1; z >= minCoveringZoom; --z) {
const Tile::ID parent_id = Tile::parent(id, z);
const Tile::ID parent_id = id.parent(z);
const TileData::State state = hasTile(parent_id);
if (state == TileData::State::parsed) {
retain.emplace_front(parent_id);

View File

@@ -8,10 +8,10 @@ Tile::Tile(const ID& id)
: id(id) {
}
Tile::ID Tile::parent(const ID& id, int32_t z) {
assert(z < id.z);
ID pos(id);
while (pos.z > z) {
Tile::ID Tile::ID::parent(int32_t parent_z) const {
assert(parent_z < z);
ID pos(z, x, y);
while (pos.z > parent_z) {
--pos.z;
pos.x = floor(pos.x / 2);
pos.y = floor(pos.y / 2);
@@ -19,25 +19,27 @@ Tile::ID Tile::parent(const ID& id, int32_t z) {
return pos;
}
std::forward_list<Tile::ID> Tile::children(const ID& id, int32_t z) {
assert(z > id.z);
int32_t factor = pow(2, z - id.z);
std::forward_list<Tile::ID> Tile::ID::children(int32_t child_z) const {
assert(child_z > z);
int32_t factor = pow(2, child_z - z);
std::forward_list<ID> children;
for (int32_t y = id.y * factor, y_max = (id.y + 1) * factor; y < y_max; ++y) {
for (int32_t x = id.x * factor, x_max = (id.x + 1) * factor; x < x_max; ++x) {
children.emplace_front(x, y, z);
for (int32_t ty = y * factor, y_max = (y + 1) * factor; ty < y_max; ++ty) {
for (int32_t tx = x * factor, x_max = (x + 1) * factor; tx < x_max; ++tx) {
children.emplace_front(child_z, tx, ty);
}
}
return children;
}
void Tile::ID::normalize() {
int32_t dim = pow(2, z);
while (x < 0) x += dim;
while (x >= dim) x -= dim;
}
Tile::ID Tile::normalize(const ID& id) {
ID pos(id);
int32_t dim = pow(2, id.z);
while (pos.x < 0) pos.x += dim;
while (pos.x >= dim) pos.x -= dim;
Tile::ID Tile::ID::normalized() const {
ID pos(z, x, y);
pos.normalize();
return pos;
}

View File

@@ -235,7 +235,7 @@ double Transform::pixel_y() const {
return center + y;
}
void Transform::matrixFor(mat4& matrix, const vec3<int32_t>& id) const {
void Transform::matrixFor(mat4& matrix, const Tile::ID& id) const {
const double tile_scale = pow(2, id.z);
const double tile_size = scale * util::tileSize / tile_scale;