Skip to content

Commit 4bfa132

Browse files
committed
Refactor expire by geometry code, disable expire when not using 3857
Split up code into functions for each geometry type. Adds support for geometry types that have been missing so far (multipoint, geometry collection). When using a target SRS other than Mercator (EPSG:3857) expire didn't work before, it is now explicitly disabled (with a warning) in this case. (This applies only to the pgsql output, the flex output sets the SRS per table. There is currently no warning in this case, but we are moving away from the expire configuration on the command line for the flex output anyway, so I'll leave it at that for the moment.)
1 parent c7438e3 commit 4bfa132

7 files changed

Lines changed: 527 additions & 51 deletions

File tree

src/expire-tiles.cpp

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -78,41 +78,57 @@ void expire_tiles::from_point_list(geom::point_list_t const &list)
7878
});
7979
}
8080

81-
void expire_tiles::from_geometry(geom::geometry_t const &geom)
81+
void expire_tiles::from_geometry(geom::point_t const &geom)
82+
{
83+
geom::box_t const box = geom::envelope(geom);
84+
from_bbox(box);
85+
}
86+
87+
void expire_tiles::from_geometry(geom::linestring_t const &geom)
8288
{
83-
if (geom.srid() != 3857) {
84-
return;
89+
from_point_list(geom);
90+
}
91+
92+
void expire_tiles::from_polygon_boundary(geom::polygon_t const &geom)
93+
{
94+
from_point_list(geom.outer());
95+
for (auto const &inner : geom.inners()) {
96+
from_point_list(inner);
8597
}
98+
}
8699

87-
if (geom.is_point()) {
88-
auto const box = geom::envelope(geom);
89-
from_bbox(box);
90-
} else if (geom.is_linestring()) {
91-
from_point_list(geom.get<geom::linestring_t>());
92-
} else if (geom.is_multilinestring()) {
93-
for (auto const &list : geom.get<geom::multilinestring_t>()) {
94-
from_point_list(list);
95-
}
96-
} else if (geom.is_polygon() || geom.is_multipolygon()) {
97-
auto const box = geom::envelope(geom);
98-
if (from_bbox(box)) {
99-
if (geom.is_polygon()) {
100-
from_point_list(geom.get<geom::polygon_t>().outer());
101-
for (auto const &inner : geom.get<geom::polygon_t>().inners()) {
102-
from_point_list(inner);
103-
}
104-
} else if (geom.is_multipolygon()) {
105-
for (auto const &polygon : geom.get<geom::multipolygon_t>()) {
106-
from_point_list(polygon.outer());
107-
for (auto const &inner : polygon.inners()) {
108-
from_point_list(inner);
109-
}
110-
}
111-
}
100+
void expire_tiles::from_geometry(geom::polygon_t const &geom)
101+
{
102+
geom::box_t const box = geom::envelope(geom);
103+
if (from_bbox(box)) {
104+
/* Bounding box too big - just expire tiles on the boundary */
105+
from_polygon_boundary(geom);
106+
}
107+
}
108+
109+
void expire_tiles::from_geometry(geom::multipolygon_t const &geom)
110+
{
111+
geom::box_t const box = geom::envelope(geom);
112+
if (from_bbox(box)) {
113+
/* Bounding box too big - just expire tiles on the boundary */
114+
for (auto const &sgeom : geom) {
115+
from_polygon_boundary(sgeom);
112116
}
113117
}
114118
}
115119

120+
void expire_tiles::from_geometry(geom::geometry_t const &geom)
121+
{
122+
geom.visit([&](auto const &g) { from_geometry(g); });
123+
}
124+
125+
void expire_tiles::from_geometry_if_3857(geom::geometry_t const &geom)
126+
{
127+
if (geom.srid() == 3857) {
128+
from_geometry(geom);
129+
}
130+
}
131+
116132
/*
117133
* Expire tiles that a line crosses
118134
*/
@@ -281,11 +297,8 @@ std::size_t output_tiles_to_file(quadkey_list_t const &tiles_maxzoom,
281297

282298
int expire_from_result(expire_tiles *expire, pg_result_t const &result)
283299
{
284-
if (!expire->enabled()) {
285-
return -1;
286-
}
287-
288300
auto const num_tuples = result.num_tuples();
301+
289302
for (int i = 0; i < num_tuples; ++i) {
290303
char const *const wkb = result.get_value(i, 0);
291304
expire->from_geometry(ewkb_to_geom(decode_hex(wkb)));

src/expire-tiles.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,26 @@ class expire_tiles
3232

3333
bool enabled() const noexcept { return m_maxzoom != 0; }
3434

35+
void from_polygon_boundary(geom::polygon_t const &geom);
36+
37+
void from_geometry(geom::nullgeom_t const & /*geom*/) {}
38+
void from_geometry(geom::point_t const &geom);
39+
void from_geometry(geom::linestring_t const &geom);
40+
void from_geometry(geom::polygon_t const &geom);
41+
void from_geometry(geom::multipolygon_t const &geom);
42+
43+
template <typename T>
44+
void from_geometry(geom::multigeometry_t<T> const &geom)
45+
{
46+
for (auto const &sgeom : geom) {
47+
from_geometry(sgeom);
48+
}
49+
}
50+
3551
void from_geometry(geom::geometry_t const &geom);
3652

53+
void from_geometry_if_3857(geom::geometry_t const &geom);
54+
3755
int from_bbox(geom::box_t const &box);
3856

3957
/**

src/options.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,12 @@ void options_t::check_options()
710710
"large and has been set to 31.");
711711
}
712712

713+
if (expire_tiles_zoom != 0 && projection->target_srs() != 3857) {
714+
log_warn("Expire has been enabled (with -e or --expire-tiles) but "
715+
"target SRS is not Mercator (EPSG:3857). Expire disabled!");
716+
expire_tiles_zoom = 0;
717+
}
718+
713719
if (output_backend == "flex" || output_backend == "gazetteer") {
714720
if (style == DEFAULT_STYLE) {
715721
throw std::runtime_error{

src/output-flex.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -711,13 +711,13 @@ void output_flex_t::write_column(
711711
type == table_column_type::multilinestring ||
712712
type == table_column_type::multipolygon);
713713
if (geom->srid() == column.srid()) {
714-
m_expire.from_geometry(*geom);
714+
m_expire.from_geometry_if_3857(*geom);
715715
copy_mgr->add_hex_geom(geom_to_ewkb(*geom, wrap_multi));
716716
} else {
717717
auto const proj =
718718
reprojection::create_projection(column.srid());
719719
auto const tgeom = geom::transform(*geom, *proj);
720-
m_expire.from_geometry(tgeom);
720+
m_expire.from_geometry_if_3857(tgeom);
721721
copy_mgr->add_hex_geom(geom_to_ewkb(tgeom, wrap_multi));
722722
}
723723
} else {
@@ -1681,7 +1681,7 @@ void output_flex_t::add_row(table_connection_t *table_connection,
16811681

16821682
auto const geoms = geom::split_multi(std::move(geom), split_multi);
16831683
for (auto const &sgeom : geoms) {
1684-
m_expire.from_geometry(sgeom);
1684+
m_expire.from_geometry_if_3857(sgeom);
16851685
write_row(table_connection, object.type(), id, sgeom,
16861686
table.geom_column().srid());
16871687
}
@@ -1906,15 +1906,12 @@ void output_flex_t::delete_from_table(table_connection_t *table_connection,
19061906
osmium::item_type type, osmid_t osm_id)
19071907
{
19081908
assert(table_connection);
1909-
auto const id = table_connection->table().map_id(type, osm_id);
1909+
auto const &table = table_connection->table();
1910+
auto const id = table.map_id(type, osm_id);
19101911

1911-
if (m_expire.enabled() && table_connection->table().has_geom_column()) {
1912+
if (m_expire.enabled() && table.has_geom_column() &&
1913+
table.geom_column().srid() == 3857) {
19121914
auto const result = table_connection->get_geom_by_id(type, id);
1913-
1914-
if (result.num_tuples() == 0) {
1915-
return;
1916-
}
1917-
19181915
expire_from_result(&m_expire, result);
19191916
}
19201917

src/output-pgsql.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ void output_pgsql_t::pgsql_out_way(osmium::Way const &way, taglist_t *tags,
6767

6868
auto const wkb = geom_to_ewkb(projected_geom);
6969
if (!wkb.empty()) {
70-
m_expire.from_geometry(projected_geom);
70+
m_expire.from_geometry_if_3857(projected_geom);
7171
if (m_enable_way_area) {
7272
double const area = calculate_area(
7373
get_options()->reproject_area, geom, projected_geom);
@@ -82,7 +82,7 @@ void output_pgsql_t::pgsql_out_way(osmium::Way const &way, taglist_t *tags,
8282
auto const geoms = geom::split_multi(geom::segmentize(
8383
geom::transform(geom::create_linestring(way), *m_proj), split_at));
8484
for (auto const &sgeom : geoms) {
85-
m_expire.from_geometry(sgeom);
85+
m_expire.from_geometry_if_3857(sgeom);
8686
auto const wkb = geom_to_ewkb(sgeom);
8787
m_tables[t_line]->write_row(way.id(), *tags, wkb);
8888
if (roads) {
@@ -169,7 +169,7 @@ void output_pgsql_t::node_add(osmium::Node const &node)
169169
}
170170

171171
auto const geom = geom::transform(geom::create_point(node), *m_proj);
172-
m_expire.from_geometry(geom);
172+
m_expire.from_geometry_if_3857(geom);
173173
auto const wkb = geom_to_ewkb(geom);
174174
m_tables[t_point]->write_row(node.id(), outtags, wkb);
175175
}
@@ -272,7 +272,7 @@ void output_pgsql_t::pgsql_process_relation(osmium::Relation const &rel)
272272
}
273273
auto const geoms = geom::split_multi(std::move(projected_geom));
274274
for (auto const &sgeom : geoms) {
275-
m_expire.from_geometry(sgeom);
275+
m_expire.from_geometry_if_3857(sgeom);
276276
auto const wkb = geom_to_ewkb(sgeom);
277277
m_tables[t_line]->write_row(-rel.id(), outtags, wkb);
278278
if (roads) {
@@ -288,7 +288,7 @@ void output_pgsql_t::pgsql_process_relation(osmium::Relation const &rel)
288288
!get_options()->enable_multi);
289289
for (auto const &sgeom : geoms) {
290290
auto const projected_geom = geom::transform(sgeom, *m_proj);
291-
m_expire.from_geometry(projected_geom);
291+
m_expire.from_geometry_if_3857(projected_geom);
292292
auto const wkb = geom_to_ewkb(projected_geom);
293293
if (m_enable_way_area) {
294294
double const area = calculate_area(
@@ -325,8 +325,12 @@ void output_pgsql_t::relation_add(osmium::Relation const &rel)
325325
* contain the change for that also. */
326326
void output_pgsql_t::node_delete(osmid_t osm_id)
327327
{
328-
auto const results = m_tables[t_point]->get_wkb(osm_id);
329-
if (expire_from_result(&m_expire, results) != 0) {
328+
if (m_expire.enabled()) {
329+
auto const results = m_tables[t_point]->get_wkb(osm_id);
330+
if (expire_from_result(&m_expire, results) != 0) {
331+
m_tables[t_point]->delete_row(osm_id);
332+
}
333+
} else {
330334
m_tables[t_point]->delete_row(osm_id);
331335
}
332336
}
@@ -336,8 +340,12 @@ void output_pgsql_t::delete_from_output_and_expire(osmid_t id)
336340
m_tables[t_roads]->delete_row(id);
337341

338342
for (auto table : {t_line, t_poly}) {
339-
auto const results = m_tables[table]->get_wkb(id);
340-
if (expire_from_result(&m_expire, results) != 0) {
343+
if (m_expire.enabled()) {
344+
auto const results = m_tables[table]->get_wkb(id);
345+
if (expire_from_result(&m_expire, results) != 0) {
346+
m_tables[table]->delete_row(id);
347+
}
348+
} else {
341349
m_tables[table]->delete_row(id);
342350
}
343351
}

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ set_test(test-check-input LABELS NoDB)
4141
set_test(test-db-copy-thread)
4242
set_test(test-db-copy-mgr)
4343
set_test(test-domain-matcher LABELS NoDB)
44+
set_test(test-expire-from-geometry LABELS NoDB)
4445
set_test(test-expire-tiles LABELS NoDB)
4546
set_test(test-geom-box LABELS NoDB)
4647
set_test(test-geom-collections LABELS NoDB)

0 commit comments

Comments
 (0)