mirror of
https://github.com/osm2pgsql-dev/osm2pgsql.git
synced 2025-08-19 16:28:16 +00:00
503 lines
16 KiB
C++
503 lines
16 KiB
C++
/**
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*
|
|
* This file is part of osm2pgsql (https://osm2pgsql.org/).
|
|
*
|
|
* Copyright (C) 2006-2024 by the osm2pgsql developer community.
|
|
* For a full list of authors see the git log.
|
|
*/
|
|
|
|
#include <catch.hpp>
|
|
|
|
#include <random>
|
|
#include <set>
|
|
|
|
#include "expire-tiles.hpp"
|
|
#include "reprojection.hpp"
|
|
#include "tile-output.hpp"
|
|
#include "tile.hpp"
|
|
|
|
static std::shared_ptr<reprojection> defproj{
|
|
reprojection::create_projection(PROJ_SPHERE_MERC)};
|
|
|
|
// We are using zoom level 12 here, because at that level a tile is about
|
|
// 10,000 units wide/high which gives us easy numbers to work with.
|
|
static constexpr uint32_t const zoom = 12;
|
|
|
|
TEST_CASE("expire null geometry does nothing", "[NoDB]")
|
|
{
|
|
expire_config_t const expire_config;
|
|
expire_tiles et{zoom, defproj};
|
|
|
|
SECTION("geom")
|
|
{
|
|
geom::geometry_t const geom{};
|
|
et.from_geometry(geom, expire_config);
|
|
}
|
|
|
|
SECTION("geom with check")
|
|
{
|
|
geom::geometry_t geom{};
|
|
geom.set_srid(3857);
|
|
et.from_geometry_if_3857(geom, expire_config);
|
|
}
|
|
|
|
REQUIRE(et.get_tiles().empty());
|
|
}
|
|
|
|
TEST_CASE("expire point at tile boundary", "[NoDB]")
|
|
{
|
|
expire_config_t const expire_config;
|
|
expire_tiles et{zoom, defproj};
|
|
|
|
geom::point_t const pt{0.0, 0.0};
|
|
|
|
SECTION("point") { et.from_geometry(pt, expire_config); }
|
|
|
|
SECTION("geom")
|
|
{
|
|
geom::geometry_t const geom{pt};
|
|
et.from_geometry(geom, expire_config);
|
|
}
|
|
|
|
SECTION("geom with check")
|
|
{
|
|
geom::geometry_t geom{pt};
|
|
geom.set_srid(3857);
|
|
et.from_geometry_if_3857(geom, expire_config);
|
|
}
|
|
|
|
auto const tiles = et.get_tiles();
|
|
REQUIRE(tiles.size() == 4);
|
|
CHECK(tile_t::from_quadkey(tiles[0], zoom) == tile_t{zoom, 2047, 2047});
|
|
CHECK(tile_t::from_quadkey(tiles[1], zoom) == tile_t{zoom, 2048, 2047});
|
|
CHECK(tile_t::from_quadkey(tiles[2], zoom) == tile_t{zoom, 2047, 2048});
|
|
CHECK(tile_t::from_quadkey(tiles[3], zoom) == tile_t{zoom, 2048, 2048});
|
|
}
|
|
|
|
TEST_CASE("expire point away from tile boundary", "[NoDB]")
|
|
{
|
|
expire_config_t const expire_config;
|
|
expire_tiles et{zoom, defproj};
|
|
|
|
geom::point_t const pt{5000.0, 5000.0};
|
|
|
|
SECTION("point") { et.from_geometry(pt, expire_config); }
|
|
|
|
SECTION("geom")
|
|
{
|
|
geom::geometry_t const geom{pt};
|
|
et.from_geometry(geom, expire_config);
|
|
}
|
|
|
|
SECTION("geom with check")
|
|
{
|
|
geom::geometry_t geom{pt};
|
|
geom.set_srid(3857);
|
|
et.from_geometry_if_3857(geom, expire_config);
|
|
}
|
|
|
|
auto const tiles = et.get_tiles();
|
|
REQUIRE(tiles.size() == 1);
|
|
CHECK(tile_t::from_quadkey(tiles[0], zoom) == tile_t{zoom, 2048, 2047});
|
|
}
|
|
|
|
TEST_CASE("expire linestring away from tile boundary", "[NoDB]")
|
|
{
|
|
expire_config_t const expire_config;
|
|
expire_tiles et{zoom, defproj};
|
|
|
|
SECTION("line")
|
|
{
|
|
geom::linestring_t const line{{5000.0, 4000.0}, {5100.0, 4200.0}};
|
|
et.from_geometry(line, expire_config);
|
|
}
|
|
|
|
SECTION("geom")
|
|
{
|
|
geom::linestring_t line{{5000.0, 4000.0}, {5100.0, 4200.0}};
|
|
geom::geometry_t const geom{std::move(line)};
|
|
et.from_geometry(geom, expire_config);
|
|
}
|
|
|
|
SECTION("geom with check")
|
|
{
|
|
geom::linestring_t line{{5000.0, 4000.0}, {5100.0, 4200.0}};
|
|
geom::geometry_t geom{std::move(line)};
|
|
geom.set_srid(3857);
|
|
et.from_geometry_if_3857(geom, expire_config);
|
|
}
|
|
|
|
auto const tiles = et.get_tiles();
|
|
REQUIRE(tiles.size() == 1);
|
|
CHECK(tile_t::from_quadkey(tiles[0], zoom) == tile_t{zoom, 2048, 2047});
|
|
}
|
|
|
|
TEST_CASE("expire linestring crossing tile boundary", "[NoDB]")
|
|
{
|
|
expire_config_t const expire_config;
|
|
expire_tiles et{zoom, defproj};
|
|
|
|
SECTION("line")
|
|
{
|
|
geom::linestring_t const line{{5000.0, 5000.0}, {5000.0, 15000.0}};
|
|
et.from_geometry(line, expire_config);
|
|
}
|
|
|
|
SECTION("geom")
|
|
{
|
|
geom::linestring_t line{{5000.0, 5000.0}, {5000.0, 15000.0}};
|
|
geom::geometry_t const geom{std::move(line)};
|
|
et.from_geometry(geom, expire_config);
|
|
}
|
|
|
|
SECTION("geom with check")
|
|
{
|
|
geom::linestring_t line{{5000.0, 5000.0}, {5000.0, 15000.0}};
|
|
geom::geometry_t geom{std::move(line)};
|
|
geom.set_srid(3857);
|
|
et.from_geometry_if_3857(geom, expire_config);
|
|
}
|
|
|
|
auto const tiles = et.get_tiles();
|
|
REQUIRE(tiles.size() == 2);
|
|
CHECK(tile_t::from_quadkey(tiles[0], zoom) == tile_t{zoom, 2048, 2046});
|
|
CHECK(tile_t::from_quadkey(tiles[1], zoom) == tile_t{zoom, 2048, 2047});
|
|
}
|
|
|
|
TEST_CASE("expire small polygon", "[NoDB]")
|
|
{
|
|
expire_config_t const expire_config;
|
|
expire_tiles et{zoom, defproj};
|
|
|
|
SECTION("polygon")
|
|
{
|
|
geom::polygon_t const poly{{{5000.0, 5000.0},
|
|
{5100.0, 5000.0},
|
|
{5100.0, 5100.0},
|
|
{5000.0, 5100.0},
|
|
{5000.0, 5000.0}}};
|
|
et.from_geometry(poly, expire_config);
|
|
}
|
|
|
|
SECTION("geom")
|
|
{
|
|
geom::polygon_t poly{{{5000.0, 5000.0},
|
|
{5100.0, 5000.0},
|
|
{5100.0, 5100.0},
|
|
{5000.0, 5100.0},
|
|
{5000.0, 5000.0}}};
|
|
geom::geometry_t const geom{std::move(poly)};
|
|
et.from_geometry(geom, expire_config);
|
|
}
|
|
|
|
SECTION("geom with check")
|
|
{
|
|
geom::polygon_t poly{{{5000.0, 5000.0},
|
|
{5100.0, 5000.0},
|
|
{5100.0, 5100.0},
|
|
{5000.0, 5100.0},
|
|
{5000.0, 5000.0}}};
|
|
geom::geometry_t geom{std::move(poly)};
|
|
geom.set_srid(3857);
|
|
et.from_geometry_if_3857(geom, expire_config);
|
|
}
|
|
|
|
auto const tiles = et.get_tiles();
|
|
REQUIRE(tiles.size() == 1);
|
|
CHECK(tile_t::from_quadkey(tiles[0], zoom) == tile_t{zoom, 2048, 2047});
|
|
}
|
|
|
|
TEST_CASE("expire large polygon as bbox", "[NoDB]")
|
|
{
|
|
expire_config_t expire_config;
|
|
expire_config.mode = expire_mode::hybrid;
|
|
expire_config.full_area_limit = 40000;
|
|
expire_tiles et{zoom, defproj};
|
|
|
|
SECTION("polygon")
|
|
{
|
|
geom::polygon_t const poly{{{5000.0, 5000.0},
|
|
{25000.0, 5000.0},
|
|
{25000.0, 25000.0},
|
|
{5000.0, 25000.0},
|
|
{5000.0, 5000.0}}};
|
|
et.from_geometry(poly, expire_config);
|
|
}
|
|
|
|
SECTION("geom")
|
|
{
|
|
geom::polygon_t poly{{{5000.0, 5000.0},
|
|
{25000.0, 5000.0},
|
|
{25000.0, 25000.0},
|
|
{5000.0, 25000.0},
|
|
{5000.0, 5000.0}}};
|
|
geom::geometry_t const geom{std::move(poly)};
|
|
et.from_geometry(geom, expire_config);
|
|
}
|
|
|
|
SECTION("geom with check")
|
|
{
|
|
geom::polygon_t poly{{{5000.0, 5000.0},
|
|
{25000.0, 5000.0},
|
|
{25000.0, 25000.0},
|
|
{5000.0, 25000.0},
|
|
{5000.0, 5000.0}}};
|
|
geom::geometry_t geom{std::move(poly)};
|
|
geom.set_srid(3857);
|
|
et.from_geometry_if_3857(geom, expire_config);
|
|
}
|
|
|
|
auto const tiles = et.get_tiles();
|
|
REQUIRE(tiles.size() == 9);
|
|
CHECK(tile_t::from_quadkey(tiles[0], zoom) == tile_t{zoom, 2048, 2045});
|
|
CHECK(tile_t::from_quadkey(tiles[1], zoom) == tile_t{zoom, 2049, 2045});
|
|
CHECK(tile_t::from_quadkey(tiles[2], zoom) == tile_t{zoom, 2050, 2045});
|
|
|
|
CHECK(tile_t::from_quadkey(tiles[3], zoom) == tile_t{zoom, 2048, 2046});
|
|
CHECK(tile_t::from_quadkey(tiles[4], zoom) == tile_t{zoom, 2049, 2046});
|
|
CHECK(tile_t::from_quadkey(tiles[7], zoom) == tile_t{zoom, 2050, 2046});
|
|
|
|
CHECK(tile_t::from_quadkey(tiles[5], zoom) == tile_t{zoom, 2048, 2047});
|
|
CHECK(tile_t::from_quadkey(tiles[6], zoom) == tile_t{zoom, 2049, 2047});
|
|
CHECK(tile_t::from_quadkey(tiles[8], zoom) == tile_t{zoom, 2050, 2047});
|
|
}
|
|
|
|
TEST_CASE("expire large polygon as boundary", "[NoDB]")
|
|
{
|
|
expire_config_t expire_config;
|
|
expire_config.mode = expire_mode::hybrid;
|
|
expire_config.full_area_limit = 10000;
|
|
expire_tiles et{zoom, defproj};
|
|
|
|
SECTION("polygon")
|
|
{
|
|
geom::polygon_t const poly{{{5000.0, 5000.0},
|
|
{25000.0, 5000.0},
|
|
{25000.0, 25000.0},
|
|
{5000.0, 25000.0},
|
|
{5000.0, 5000.0}}};
|
|
et.from_geometry(poly, expire_config);
|
|
}
|
|
|
|
SECTION("polygon boundary")
|
|
{
|
|
geom::polygon_t const poly{{{5000.0, 5000.0},
|
|
{25000.0, 5000.0},
|
|
{25000.0, 25000.0},
|
|
{5000.0, 25000.0},
|
|
{5000.0, 5000.0}}};
|
|
et.from_polygon_boundary(poly, expire_config);
|
|
}
|
|
|
|
SECTION("geom")
|
|
{
|
|
geom::polygon_t poly{{{5000.0, 5000.0},
|
|
{25000.0, 5000.0},
|
|
{25000.0, 25000.0},
|
|
{5000.0, 25000.0},
|
|
{5000.0, 5000.0}}};
|
|
geom::geometry_t const geom{std::move(poly)};
|
|
et.from_geometry(geom, expire_config);
|
|
}
|
|
|
|
SECTION("geom with check")
|
|
{
|
|
geom::polygon_t poly{{{5000.0, 5000.0},
|
|
{25000.0, 5000.0},
|
|
{25000.0, 25000.0},
|
|
{5000.0, 25000.0},
|
|
{5000.0, 5000.0}}};
|
|
geom::geometry_t geom{std::move(poly)};
|
|
geom.set_srid(3857);
|
|
et.from_geometry_if_3857(geom, expire_config);
|
|
}
|
|
|
|
auto const tiles = et.get_tiles();
|
|
REQUIRE(tiles.size() == 8);
|
|
CHECK(tile_t::from_quadkey(tiles[0], zoom) == tile_t{zoom, 2048, 2045});
|
|
CHECK(tile_t::from_quadkey(tiles[1], zoom) == tile_t{zoom, 2049, 2045});
|
|
CHECK(tile_t::from_quadkey(tiles[2], zoom) == tile_t{zoom, 2050, 2045});
|
|
|
|
CHECK(tile_t::from_quadkey(tiles[3], zoom) == tile_t{zoom, 2048, 2046});
|
|
CHECK(tile_t::from_quadkey(tiles[6], zoom) == tile_t{zoom, 2050, 2046});
|
|
|
|
CHECK(tile_t::from_quadkey(tiles[4], zoom) == tile_t{zoom, 2048, 2047});
|
|
CHECK(tile_t::from_quadkey(tiles[5], zoom) == tile_t{zoom, 2049, 2047});
|
|
CHECK(tile_t::from_quadkey(tiles[7], zoom) == tile_t{zoom, 2050, 2047});
|
|
}
|
|
|
|
TEST_CASE("expire multipoint geometry", "[NoDB]")
|
|
{
|
|
expire_config_t const expire_config;
|
|
expire_tiles et{zoom, defproj};
|
|
|
|
geom::point_t const p1{0.0, 0.0};
|
|
geom::point_t const p2{15000.0, 15000.0};
|
|
|
|
SECTION("multipoint")
|
|
{
|
|
geom::multipoint_t mpt;
|
|
mpt.add_geometry(p1);
|
|
mpt.add_geometry(p2);
|
|
et.from_geometry(mpt, expire_config);
|
|
}
|
|
|
|
SECTION("geom")
|
|
{
|
|
geom::multipoint_t mpt;
|
|
mpt.add_geometry(p1);
|
|
mpt.add_geometry(p2);
|
|
geom::geometry_t const geom{std::move(mpt)};
|
|
et.from_geometry(geom, expire_config);
|
|
}
|
|
|
|
SECTION("geom with check")
|
|
{
|
|
geom::multipoint_t mpt;
|
|
mpt.add_geometry(p1);
|
|
mpt.add_geometry(p2);
|
|
geom::geometry_t geom{std::move(mpt)};
|
|
geom.set_srid(3857);
|
|
et.from_geometry_if_3857(geom, expire_config);
|
|
}
|
|
|
|
auto const tiles = et.get_tiles();
|
|
REQUIRE(tiles.size() == 5);
|
|
CHECK(tile_t::from_quadkey(tiles[0], zoom) == tile_t{zoom, 2047, 2047});
|
|
CHECK(tile_t::from_quadkey(tiles[1], zoom) == tile_t{zoom, 2049, 2046});
|
|
CHECK(tile_t::from_quadkey(tiles[2], zoom) == tile_t{zoom, 2048, 2047});
|
|
CHECK(tile_t::from_quadkey(tiles[3], zoom) == tile_t{zoom, 2047, 2048});
|
|
CHECK(tile_t::from_quadkey(tiles[4], zoom) == tile_t{zoom, 2048, 2048});
|
|
}
|
|
|
|
TEST_CASE("expire multilinestring geometry", "[NoDB]")
|
|
{
|
|
expire_config_t const expire_config;
|
|
expire_tiles et{zoom, defproj};
|
|
|
|
geom::linestring_t l1{{2000.0, 2000.0}, {3000.0, 3000.0}};
|
|
geom::linestring_t l2{{15000.0, 15000.0}, {25000.0, 15000.0}};
|
|
geom::multilinestring_t ml;
|
|
ml.add_geometry(std::move(l1));
|
|
ml.add_geometry(std::move(l2));
|
|
|
|
SECTION("multilinestring") { et.from_geometry(ml, expire_config); }
|
|
|
|
SECTION("geom")
|
|
{
|
|
geom::geometry_t const geom{std::move(ml)};
|
|
et.from_geometry(geom, expire_config);
|
|
}
|
|
|
|
auto const tiles = et.get_tiles();
|
|
REQUIRE(tiles.size() == 3);
|
|
CHECK(tile_t::from_quadkey(tiles[0], zoom) == tile_t{zoom, 2049, 2046});
|
|
CHECK(tile_t::from_quadkey(tiles[1], zoom) == tile_t{zoom, 2048, 2047});
|
|
CHECK(tile_t::from_quadkey(tiles[2], zoom) == tile_t{zoom, 2050, 2046});
|
|
}
|
|
|
|
TEST_CASE("expire multipolygon geometry", "[NoDB]")
|
|
{
|
|
expire_config_t expire_config;
|
|
expire_config.mode = expire_mode::hybrid;
|
|
expire_config.full_area_limit = 10000;
|
|
expire_tiles et{zoom, defproj};
|
|
|
|
geom::polygon_t p1{{{2000.0, 2000.0},
|
|
{2000.0, 3000.0},
|
|
{3000.0, 3000.0},
|
|
{3000.0, 2000.0},
|
|
{2000.0, 2000.0}}};
|
|
|
|
geom::polygon_t p2{{{15000.0, 15000.0},
|
|
{45000.0, 15000.0},
|
|
{45000.0, 45000.0},
|
|
{15000.0, 45000.0},
|
|
{15000.0, 15000.0}}};
|
|
p2.add_inner_ring({{25000.0, 25000.0},
|
|
{25000.0, 35000.0},
|
|
{35000.0, 35000.0},
|
|
{35000.0, 25000.0},
|
|
{25000.0, 25000.0}});
|
|
|
|
geom::multipolygon_t mp;
|
|
mp.add_geometry(std::move(p1));
|
|
mp.add_geometry(std::move(p2));
|
|
|
|
SECTION("multilinestring") { et.from_geometry(mp, expire_config); }
|
|
|
|
SECTION("geom")
|
|
{
|
|
geom::geometry_t const geom{std::move(mp)};
|
|
et.from_geometry(geom, expire_config);
|
|
}
|
|
|
|
auto const tiles = et.get_tiles();
|
|
REQUIRE(tiles.size() == 17);
|
|
|
|
std::set<quadkey_t> result;
|
|
for (auto const &tile : tiles) {
|
|
result.insert(tile);
|
|
}
|
|
|
|
std::set<quadkey_t> expected;
|
|
expected.insert(tile_t{zoom, 2048, 2047}.quadkey()); // p1
|
|
|
|
for (uint32_t x = 2049; x <= 2052; ++x) {
|
|
for (uint32_t y = 2043; y <= 2046; ++y) {
|
|
expected.insert(tile_t{zoom, x, y}.quadkey()); // p2
|
|
}
|
|
}
|
|
REQUIRE(expected == result);
|
|
}
|
|
|
|
TEST_CASE("expire geometry collection", "[NoDB]")
|
|
{
|
|
expire_config_t const expire_config;
|
|
expire_tiles et{zoom, defproj};
|
|
|
|
geom::collection_t collection;
|
|
collection.add_geometry(geom::geometry_t{geom::point_t{0.0, 0.0}});
|
|
collection.add_geometry(geom::geometry_t{
|
|
geom::linestring_t{{15000.0, 15000.0}, {25000.0, 15000.0}}});
|
|
|
|
geom::geometry_t const geom{std::move(collection)};
|
|
et.from_geometry(geom, expire_config);
|
|
|
|
auto const tiles = et.get_tiles();
|
|
REQUIRE(tiles.size() == 6);
|
|
CHECK(tile_t::from_quadkey(tiles[0], zoom) == tile_t{zoom, 2047, 2047});
|
|
CHECK(tile_t::from_quadkey(tiles[1], zoom) == tile_t{zoom, 2049, 2046});
|
|
CHECK(tile_t::from_quadkey(tiles[2], zoom) == tile_t{zoom, 2048, 2047});
|
|
CHECK(tile_t::from_quadkey(tiles[3], zoom) == tile_t{zoom, 2050, 2046});
|
|
CHECK(tile_t::from_quadkey(tiles[4], zoom) == tile_t{zoom, 2047, 2048});
|
|
CHECK(tile_t::from_quadkey(tiles[5], zoom) == tile_t{zoom, 2048, 2048});
|
|
}
|
|
|
|
TEST_CASE("expire works if in 3857", "[NoDB]")
|
|
{
|
|
expire_config_t const expire_config;
|
|
expire_tiles et{zoom, defproj};
|
|
|
|
geom::geometry_t geom{geom::point_t{0.0, 0.0}};
|
|
geom.set_srid(3857);
|
|
et.from_geometry_if_3857(geom, expire_config);
|
|
|
|
auto const tiles = et.get_tiles();
|
|
REQUIRE(tiles.size() == 4);
|
|
}
|
|
|
|
TEST_CASE("expire doesn't do anything if not in 3857", "[NoDB]")
|
|
{
|
|
expire_config_t const expire_config;
|
|
expire_tiles et{zoom, defproj};
|
|
|
|
geom::geometry_t geom{geom::point_t{0.0, 0.0}};
|
|
geom.set_srid(1234);
|
|
et.from_geometry_if_3857(geom, expire_config);
|
|
|
|
auto const tiles = et.get_tiles();
|
|
REQUIRE(tiles.empty());
|
|
}
|