Skip to content

Commit fe3d7bb

Browse files
committed
Make locator also work with geometry collections
1 parent 35c6d73 commit fe3d7bb

File tree

3 files changed

+109
-18
lines changed

3 files changed

+109
-18
lines changed

src/locator.cpp

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -88,44 +88,63 @@ void locator_t::build_index()
8888
m_rtree.insert(m_data.cbegin(), m_data.cend());
8989
}
9090

91-
std::set<std::string> locator_t::all_intersecting(geom::geometry_t const &geom)
91+
void locator_t::all_intersecting_visit(geom::geometry_t const &geom,
92+
std::set<std::string> *results)
9293
{
93-
if (m_rtree.size() < m_regions.size()) {
94-
build_index();
95-
}
96-
97-
std::set<std::string> results;
98-
99-
geom.visit(overloaded{[&](geom::nullgeom_t const & /*input*/) {},
100-
[&](geom::collection_t const & /*input*/) {}, // TODO
94+
geom.visit(overloaded{[&](geom::nullgeom_t const & /*val*/) {},
95+
[&](geom::collection_t const &val) {
96+
for (auto const &sgeom : val) {
97+
all_intersecting_visit(sgeom, results);
98+
}
99+
},
101100
[&](auto const &val) {
102101
for (auto it = begin_intersects(val);
103102
it != end_query(); ++it) {
104103
auto const &region = m_regions[it->second];
105-
results.emplace(region.name());
104+
results->emplace(region.name());
106105
}
107106
}});
108-
109-
return results;
110107
}
111108

112-
std::string locator_t::first_intersecting(geom::geometry_t const &geom)
109+
std::set<std::string> locator_t::all_intersecting(geom::geometry_t const &geom)
113110
{
114111
if (m_rtree.size() < m_regions.size()) {
115112
build_index();
116113
}
117114

118-
std::string result;
115+
std::set<std::string> results;
116+
all_intersecting_visit(geom, &results);
117+
return results;
118+
}
119119

120-
geom.visit(overloaded{[&](geom::nullgeom_t const & /*input*/) {},
121-
[&](geom::collection_t const & /*input*/) {}, // TODO
120+
void locator_t::first_intersecting_visit(geom::geometry_t const &geom,
121+
std::string *result)
122+
{
123+
geom.visit(overloaded{[&](geom::nullgeom_t const & /*val*/) {},
124+
[&](geom::collection_t const &val) {
125+
for (auto const &sgeom : val) {
126+
first_intersecting_visit(sgeom, result);
127+
if (!result->empty()) {
128+
return;
129+
}
130+
}
131+
},
122132
[&](auto const &val) {
123133
auto const it = begin_intersects(val);
124134
if (it != end_query()) {
125135
auto const &region = m_regions[it->second];
126-
result = region.name();
136+
*result = region.name();
127137
}
128138
}});
139+
}
129140

141+
std::string locator_t::first_intersecting(geom::geometry_t const &geom)
142+
{
143+
if (m_rtree.size() < m_regions.size()) {
144+
build_index();
145+
}
146+
147+
std::string result;
148+
first_intersecting_visit(geom, &result);
130149
return result;
131150
}

src/locator.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ class locator_t
9898

9999
tree_t::const_query_iterator end_query() { return m_rtree.qend(); }
100100

101+
void all_intersecting_visit(geom::geometry_t const &geom,
102+
std::set<std::string> *results);
103+
104+
void first_intersecting_visit(geom::geometry_t const &geom,
105+
std::string *result);
106+
101107
public:
102108
/// The name of this locator (for logging only)
103109
std::string const &name() const noexcept { return m_name; }

tests/bdd/flex/locator.feature

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ Feature: Locators
8080
Error in 'first_intersecting': Need locator and geometry arguments
8181
"""
8282

83-
Scenario: Use a all_intersecting() without geometry fails
83+
Scenario: Use of all_intersecting() without geometry fails
8484
Given the OSM data
8585
"""
8686
n10 v1 dV Tamenity=post_box x0.5 y0.5
@@ -231,3 +231,69 @@ Feature: Locators
231231
| node_id | region | ST_AsText(geom) |
232232
| 10 | P1 | 15 8 |
233233

234+
Scenario: Define and use a locator with relation from db
235+
Given the 10.0 grid with origin 10.0 10.0
236+
| 10 | 11 | 12 |
237+
| 13 | 14 | 15 |
238+
And the OSM data
239+
"""
240+
w29 v1 dV Tregion=P1 Nn10,n11,n14,n13,n10
241+
"""
242+
And the lua style
243+
"""
244+
local regions = osm2pgsql.define_way_table('osm2pgsql_test_regions', {
245+
{ column = 'region', type = 'text' },
246+
{ column = 'geom', type = 'polygon', projection = 4326 },
247+
})
248+
249+
function osm2pgsql.process_way(object)
250+
regions:insert({
251+
region = object.tags.region,
252+
geom = object:as_polygon(),
253+
})
254+
end
255+
"""
256+
When running osm2pgsql flex
257+
Then table osm2pgsql_test_regions contains exactly
258+
| way_id | region | ST_AsText(geom) |
259+
| 29 | P1 | (10 0,20 0,20 10,10 10, 10 0) |
260+
261+
Given the 10.0 grid with origin 10.0 10.0
262+
| 10 | 11 | 12 |
263+
| 13 | 14 | 15 |
264+
And the OSM data
265+
"""
266+
w20 v1 dV Nn10,n11,n13
267+
w21 v1 dV Nn13,n10
268+
w22 v1 dV Nn14,n15
269+
w23 v1 dV Nn12,n15
270+
r30 v1 dV Tfoo=bar Mw20@,w21@,w22@,n12@
271+
r31 v1 dV Tfoo=bar Mn12@,n15@
272+
r32 v1 dV Tfoo=bar Mw23@
273+
"""
274+
And the lua style
275+
"""
276+
local regions = osm2pgsql.define_locator({ name = 'regions' })
277+
regions:add_from_db('SELECT region, geom FROM osm2pgsql_test_regions')
278+
279+
local points = osm2pgsql.define_relation_table('osm2pgsql_test_rels', {
280+
{ column = 'region', type = 'text' },
281+
{ column = 'geom', type = 'geometry', projection = 4326 },
282+
})
283+
284+
function osm2pgsql.process_relation(object)
285+
local g = object:as_geometrycollection()
286+
local r = regions:first_intersecting(g)
287+
if r then
288+
points:insert({
289+
region = r,
290+
geom = g,
291+
})
292+
end
293+
end
294+
"""
295+
When running osm2pgsql flex
296+
Then table osm2pgsql_test_rels contains exactly
297+
| relation_id | region | ST_GeometryType(geom) |
298+
| 30 | P1 | ST_GeometryCollection |
299+

0 commit comments

Comments
 (0)