Consolidate definitions of earth circumference etc.

HEAD
Jochen Topf 2022-03-07 10:30:43 +01:00
parent 5b277d856b
commit 8249a8f0cd
3 changed files with 41 additions and 28 deletions

View File

@ -28,11 +28,9 @@
#include "options.hpp"
#include "reprojection.hpp"
#include "table.hpp"
#include "tile.hpp"
#include "wkb.hpp"
#define EARTH_CIRCUMFERENCE 40075016.68
#define HALF_EARTH_CIRCUMFERENCE (EARTH_CIRCUMFERENCE / 2)
// How many tiles worth of space to leave either side of a changed feature
static constexpr double const tile_expiry_leeway = 0.1;
@ -98,8 +96,8 @@ geom::point_t expire_tiles::coords_to_tile(geom::point_t const &point)
{
auto const c = m_projection->target_to_tile(point);
return {m_map_width * (0.5 + c.x() / EARTH_CIRCUMFERENCE),
m_map_width * (0.5 - c.y() / EARTH_CIRCUMFERENCE)};
return {m_map_width * (0.5 + c.x() / tile_t::earth_circumference),
m_map_width * (0.5 - c.y() / tile_t::earth_circumference)};
}
void expire_tiles::from_point_list(geom::point_list_t const &list)
@ -220,12 +218,13 @@ int expire_tiles::from_bbox(geom::box_t const &box)
double const width = box.width();
double const height = box.height();
if (width > HALF_EARTH_CIRCUMFERENCE + 1) {
if (width > tile_t::half_earth_circumference + 1) {
/* Over half the planet's width within the bounding box - assume the
box crosses the international date line and split it into two boxes */
int ret =
from_bbox({-HALF_EARTH_CIRCUMFERENCE, box.min_y(), box.min_x(), box.max_y()});
ret += from_bbox({box.max_x(), box.min_y(), HALF_EARTH_CIRCUMFERENCE, box.max_y()});
int ret = from_bbox({-tile_t::half_earth_circumference, box.min_y(),
box.min_x(), box.max_y()});
ret += from_bbox({box.max_x(), box.min_y(),
tile_t::half_earth_circumference, box.max_y()});
return ret;
}

View File

@ -21,6 +21,10 @@
class tile_t
{
public:
static constexpr double const earth_circumference = 40075016.68;
static constexpr double const half_earth_circumference =
earth_circumference / 2;
/// Construct an invalid tile.
tile_t() noexcept = default;
@ -62,20 +66,32 @@ public:
/// The width/height of the tile in web mercator (EPSG:3857) coordinates.
double extent() const noexcept
{
return (2 * extent_max) / static_cast<double>(1UL << m_zoom);
return earth_circumference / static_cast<double>(1UL << m_zoom);
}
/// Minimum X coordinate of this tile in web mercator (EPSG:3857) units.
double xmin() const noexcept { return -extent_max + m_x * extent(); }
double xmin() const noexcept
{
return -half_earth_circumference + m_x * extent();
}
/// Maximum X coordinate of this tile in web mercator (EPSG:3857) units.
double xmax() const noexcept { return -extent_max + (m_x + 1) * extent(); }
double xmax() const noexcept
{
return -half_earth_circumference + (m_x + 1) * extent();
}
/// Minimum Y coordinate of this tile in web mercator (EPSG:3857) units.
double ymin() const noexcept { return extent_max - (m_y + 1) * extent(); }
double ymin() const noexcept
{
return half_earth_circumference - (m_y + 1) * extent();
}
/// Maximum Y coordinate of this tile in web mercator (EPSG:3857) units.
double ymax() const noexcept { return extent_max - m_y * extent(); }
double ymax() const noexcept
{
return half_earth_circumference - m_y * extent();
}
/**
* Convert a point from web mercator (EPSG:3857) coordinates to
@ -140,7 +156,6 @@ public:
static tile_t from_quadkey(uint64_t quadkey, uint32_t zoom) noexcept;
private:
static constexpr double const extent_max = 20037508.342789244;
static constexpr uint32_t const invalid_zoom =
std::numeric_limits<uint32_t>::max();
static constexpr uint32_t const max_zoom = 32;

View File

@ -11,8 +11,6 @@
#include "tile.hpp"
static constexpr double const world = 20037508.342789244;
TEST_CASE("invalid tile", "[NoDB]")
{
tile_t const tile;
@ -57,16 +55,16 @@ TEST_CASE("tile_t coordinates zoom=0", "[NoDB]")
{
tile_t const tile{0, 0, 0};
REQUIRE(tile.xmin() == Approx(-world));
REQUIRE(tile.ymin() == Approx(-world));
REQUIRE(tile.xmax() == Approx(world));
REQUIRE(tile.ymax() == Approx(world));
REQUIRE(tile.xmin() == Approx(-tile_t::half_earth_circumference));
REQUIRE(tile.ymin() == Approx(-tile_t::half_earth_circumference));
REQUIRE(tile.xmax() == Approx(tile_t::half_earth_circumference));
REQUIRE(tile.ymax() == Approx(tile_t::half_earth_circumference));
REQUIRE(tile.center().x() == Approx(0.0));
REQUIRE(tile.center().y() == Approx(0.0));
REQUIRE(tile.center() == geom::point_t{0.0, 0.0});
REQUIRE(tile.extent() == Approx(world * 2));
REQUIRE(tile.extent() == Approx(tile_t::earth_circumference));
geom::point_t const p{12345.6, 7891.0};
auto const tp = tile.to_tile_coords(p, 256);
@ -81,17 +79,18 @@ TEST_CASE("tile_t coordinates zoom=2", "[NoDB]")
{
tile_t const tile{2, 1, 2};
REQUIRE(tile.xmin() == Approx(-world / 2));
REQUIRE(tile.ymin() == Approx(-world / 2));
REQUIRE(tile.xmin() == Approx(-tile_t::half_earth_circumference / 2));
REQUIRE(tile.ymin() == Approx(-tile_t::half_earth_circumference / 2));
REQUIRE(tile.xmax() == Approx(0.0));
REQUIRE(tile.ymax() == Approx(0.0));
REQUIRE(tile.center().x() == Approx(-world / 4));
REQUIRE(tile.center().y() == Approx(-world / 4));
REQUIRE(tile.center().x() == Approx(-tile_t::half_earth_circumference / 4));
REQUIRE(tile.center().y() == Approx(-tile_t::half_earth_circumference / 4));
REQUIRE(tile.extent() == Approx(world / 2));
REQUIRE(tile.extent() == Approx(tile_t::half_earth_circumference / 2));
geom::point_t const p{-world / 4, -world / 8};
geom::point_t const p{-tile_t::half_earth_circumference / 4,
-tile_t::half_earth_circumference / 8};
auto const tp = tile.to_tile_coords(p, 4096);
REQUIRE(tp.x() == Approx(2048));
REQUIRE(tp.y() == Approx(2048 + 1024));