Skip to content

Commit

Permalink
Merge pull request #76 from ndsev/tile-id-neighbor
Browse files Browse the repository at this point in the history
Implement TileId::neighbor() including test.
  • Loading branch information
josephbirkner authored Aug 9, 2024
2 parents f5a8825 + 225cc44 commit 40317c2
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 1 deletion.
7 changes: 7 additions & 0 deletions libs/model/include/mapget/model/tileid.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ struct TileId
*/
static TileId fromWgs84(double longitude, double latitude, uint16_t zoomLevel);

/**
* Get the neighbor for a mapget tile id. Tile row will be clamped to [0, maxForLevel],
* so a positive/negative wraparound is not possible. The tile id column will wrap at the
* antimeridian. Note: The implementation will only work for offset values [-1, 0, 1].
*/
[[nodiscard]] TileId neighbor(int32_t offsetX, int32_t offsetY) const;

/**
* Get the center of the tile in Wgs84.
*/
Expand Down
27 changes: 26 additions & 1 deletion libs/model/src/tileid.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "tileid.h"
#include <cmath>
#include <algorithm>
#include <cmath>
#include "mapget/log.h"

namespace mapget
{
Expand Down Expand Up @@ -68,6 +69,30 @@ TileId TileId::fromWgs84(double longitude, double latitude, uint16_t zoomLevel)
return {(uint16_t)x, (uint16_t)y, zoomLevel};
}

TileId TileId::neighbor(int32_t offsetX, int32_t offsetY) const
{
if (glm::abs(offsetX) > 1 || glm::abs(offsetY) > 1) {
raise("TileId::neighbor() called with offset value greater than 1 or less than -1.");
}

auto const maxCol = static_cast<int64_t>(1ull << (z() + 1)) - 1;
auto const maxRow = static_cast<int64_t>(1ull << z()) - 1;

auto resultX = x();
auto resultY = y();

if (offsetX == -1 && resultX == 0)
resultX = maxCol;
else if (offsetX == 1 && resultX == maxCol)
resultX = 0;
else
resultX += offsetX;

if (offsetY == -1 && resultY > 0 || offsetY == 1 && resultY < maxRow)
resultY += offsetY;
return TileId(resultX, resultY, z()).value_;
}

Point TileId::center() const {
auto extent = size();
auto lon = MIN_LON + (static_cast<double>(x()) + 0.5) * extent.x;
Expand Down
18 changes: 18 additions & 0 deletions test/unit/test-model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,4 +372,22 @@ TEST_CASE("TileId", "[TileId]") {
REQUIRE_EQUAL(tile.ne(), {0, 90});
REQUIRE_EQUAL(tile.size(), {180, 180});
}

SECTION("Neighbor") {
TileId tile(0, 0, 1);
REQUIRE(tile.neighbor(1, 0) == TileId(1, 0, 1));
REQUIRE(tile.neighbor(0, 1) == TileId(0, 1, 1));
REQUIRE(tile.neighbor(-1, -1) == TileId(3, 0, 1)); // Wrap around

TileId tile2(3, 1, 1);
REQUIRE(tile2.neighbor(-1, -1) == TileId(2, 0, 1));
REQUIRE(tile2.neighbor(1, 1) == TileId(0, 1, 1)); // Wrap around

REQUIRE_THROWS(tile2.neighbor(2, -2));
REQUIRE_THROWS(tile2.neighbor(-2, 2));
REQUIRE_THROWS(tile2.neighbor(0, 3));
REQUIRE_THROWS(tile2.neighbor(0, -3));
REQUIRE_THROWS(tile2.neighbor(2, 0));
REQUIRE_THROWS(tile2.neighbor(-2, 0));
}
}

0 comments on commit 40317c2

Please sign in to comment.