Skip to content

Commit 4fc07d6

Browse files
committed
Add function for creating multipoint geometries from relations
This adds the C++ create_multipoint() function analogous to the create_multilinestring() and create_multipolygon() functions.
1 parent 5b5685f commit 4fc07d6

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

src/geom-from-osm.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,37 @@ geometry_t create_polygon(osmium::Way const &way)
9595
return geom;
9696
}
9797

98+
void create_multipoint(geometry_t *geom, osmium::memory::Buffer const &buffer)
99+
{
100+
auto nodes = buffer.select<osmium::Node>();
101+
if (nodes.size() == 1) {
102+
auto const location = nodes.cbegin()->location();
103+
if (location.valid()) {
104+
geom->set<point_t>() = point_t{location};
105+
} else {
106+
geom->reset();
107+
}
108+
} else {
109+
auto &multiline = geom->set<multipoint_t>();
110+
for (auto const &node : nodes) {
111+
auto const location = node.location();
112+
if (location.valid()) {
113+
multiline.add_geometry(point_t{location});
114+
}
115+
}
116+
if (multiline.num_geometries() == 0) {
117+
geom->reset();
118+
}
119+
}
120+
}
121+
122+
geometry_t create_multipoint(osmium::memory::Buffer const &buffer)
123+
{
124+
geometry_t geom{};
125+
create_multipoint(&geom, buffer);
126+
return geom;
127+
}
128+
98129
void create_multilinestring(geometry_t *geom,
99130
osmium::memory::Buffer const &buffer,
100131
bool force_multi)

src/geom-from-osm.hpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,33 @@ void create_polygon(geometry_t *geom, osmium::Way const &way);
8989
*/
9090
[[nodiscard]] geometry_t create_polygon(osmium::Way const &way);
9191

92+
/**
93+
* Create a multipoint geometry from a bunch of nodes (usually this would be
94+
* used for member nodes of a relation). The result is multipoint geometry
95+
* (or a point geometry if there is only one point).
96+
*
97+
* If there are no (valid) points, a null geometry is returned.
98+
*
99+
* \param geom Pointer to an existing geometry which will be used as output.
100+
* \param ways Buffer containing all the input ways. Object types other than
101+
* ways in the buffer are ignored.
102+
*/
103+
void create_multipoint(geometry_t *geom, osmium::memory::Buffer const &buffer);
104+
105+
/**
106+
* Create a multipoint geometry from a bunch of nodes (usually this would be
107+
* used for member nodes of a relation). The result is multipoint geometry
108+
* (or a point geometry if there is only one point).
109+
*
110+
* If there are no (valid) points, a null geometry is returned.
111+
*
112+
* \param ways Buffer containing all the input nodes. Object types other than
113+
* nodes in the buffer are ignored.
114+
* \returns The created geometry.
115+
*/
116+
[[nodiscard]] geometry_t
117+
create_multipoint(osmium::memory::Buffer const &buffer);
118+
92119
/**
93120
* Create a multilinestring geometry from a bunch of ways (usually this
94121
* would be used for member ways of a relation). The result is always a

tests/test-geom-multipoints.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,31 @@ TEST_CASE("multipoint_t with several points", "[NoDB]")
6767
REQUIRE(geometry_n(geom, 2) == geom::geometry_t{std::move(p1)});
6868
REQUIRE(geometry_n(geom, 3) == geom::geometry_t{std::move(p2)});
6969
}
70+
71+
TEST_CASE("create_multipoint from OSM data", "[NoDB]")
72+
{
73+
test_buffer_t buffer;
74+
buffer.add_node("n10 x1 y0");
75+
buffer.add_way("w20 Nn1x1y1,n2x2y1");
76+
buffer.add_node("n11 x1 y1");
77+
buffer.add_node("n12 x3 y2");
78+
buffer.add_way("w21 Nn3x10y10,n4x10y11");
79+
buffer.add_node("n13 x3 y1");
80+
buffer.add_relation("r30 Mw20@");
81+
82+
auto const geom = geom::create_multipoint(buffer.buffer());
83+
84+
REQUIRE(geometry_type(geom) == "MULTIPOINT");
85+
REQUIRE(dimension(geom) == 0);
86+
REQUIRE(num_geometries(geom) == 4);
87+
88+
auto const &c = geom.get<geom::multipoint_t>();
89+
REQUIRE(c[0] == geom::point_t{1, 0});
90+
REQUIRE(c[1] == geom::point_t{1, 1});
91+
REQUIRE(c[2] == geom::point_t{3, 2});
92+
REQUIRE(c[3] == geom::point_t{3, 1});
93+
94+
REQUIRE(area(geom) == Approx(0.0));
95+
REQUIRE(length(geom) == Approx(0.0));
96+
REQUIRE(centroid(geom) == geom::geometry_t{geom::point_t{2, 1}});
97+
}

0 commit comments

Comments
 (0)