Skip to content

Commit 18662b7

Browse files
committed
Add missing WKB MultiPoint parser implementation
1 parent 9a2539e commit 18662b7

File tree

2 files changed

+65
-8
lines changed

2 files changed

+65
-8
lines changed

src/wkb.cpp

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -207,15 +207,19 @@ class make_ewkb_visitor
207207

208208
std::string operator()(geom::point_t const &geom) const
209209
{
210-
// 9 byte header plus one set of coordinates
211-
constexpr const std::size_t size = 9 + 2 * 8;
212-
213210
std::string data;
214211

215-
data.reserve(size);
216-
write_point(&data, geom, m_srid);
217-
218-
assert(data.size() == size);
212+
if (m_ensure_multi) {
213+
write_header(&data, wkb_multi_point, m_srid);
214+
write_length(&data, 1);
215+
write_point(&data, geom);
216+
} else {
217+
// 9 byte header plus one set of coordinates
218+
constexpr const std::size_t size = 9 + 2 * 8;
219+
data.reserve(size);
220+
write_point(&data, geom, m_srid);
221+
assert(data.size() == size);
222+
}
219223

220224
return data;
221225
}
@@ -317,7 +321,7 @@ class ewkb_parser_t
317321
parse_polygon(&geom.set<geom::polygon_t>());
318322
break;
319323
case geometry_type::wkb_multi_point:
320-
// XXX not implemented yet
324+
parse_multi_point(&geom);
321325
break;
322326
case geometry_type::wkb_multi_line:
323327
parse_multi_linestring(&geom);
@@ -448,6 +452,28 @@ class ewkb_parser_t
448452
}
449453
}
450454

455+
void parse_multi_point(geom::geometry_t *geom)
456+
{
457+
auto &multipoint = geom->set<geom::multipoint_t>();
458+
auto const num_geoms = parse_length();
459+
if (num_geoms == 0) {
460+
throw std::runtime_error{
461+
"Invalid WKB geometry: Multipoint without points"};
462+
}
463+
464+
multipoint.reserve(num_geoms);
465+
for (uint32_t i = 0; i < num_geoms; ++i) {
466+
auto &point = multipoint.emplace_back();
467+
uint32_t const type = parse_header();
468+
if (type != geometry_type::wkb_point) {
469+
throw std::runtime_error{
470+
"Invalid WKB geometry: Multipoint containing"
471+
" something other than point: {}"_format(type)};
472+
}
473+
parse_point(&point);
474+
}
475+
}
476+
451477
void parse_multi_linestring(geom::geometry_t *geom)
452478
{
453479
auto &multilinestring = geom->set<geom::multilinestring_t>();

tests/test-wkb.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,37 @@ TEST_CASE("wkb: polygon with inner rings", "[NoDB]")
8383
geom.get<geom::polygon_t>().inners().front());
8484
}
8585

86+
TEST_CASE("wkb: point as multipoint", "[NoDB]")
87+
{
88+
geom::geometry_t geom{geom::point_t{1.2, 2.3}, 47};
89+
90+
auto const result = ewkb_to_geom(geom_to_ewkb(geom, true));
91+
REQUIRE(result.is_multipoint());
92+
REQUIRE(result.srid() == 47);
93+
auto const &rmp = result.get<geom::multipoint_t>();
94+
REQUIRE(rmp.num_geometries() == 1);
95+
96+
REQUIRE(rmp[0] == geom.get<geom::point_t>());
97+
}
98+
99+
TEST_CASE("wkb: multipoint", "[NoDB]")
100+
{
101+
geom::geometry_t geom{geom::multipoint_t{}, 46};
102+
103+
auto &mp = geom.get<geom::multipoint_t>();
104+
mp.emplace_back(geom::point_t{{1.2, 2.3}});
105+
mp.emplace_back(geom::point_t{{7.0, 7.0}});
106+
107+
auto const result = ewkb_to_geom(geom_to_ewkb(geom));
108+
REQUIRE(result.is_multipoint());
109+
REQUIRE(result.srid() == 46);
110+
auto const &rmp = result.get<geom::multipoint_t>();
111+
REQUIRE(rmp.num_geometries() == 2);
112+
113+
REQUIRE(rmp[0] == mp[0]);
114+
REQUIRE(rmp[1] == mp[1]);
115+
}
116+
86117
TEST_CASE("wkb: linestring as multilinestring", "[NoDB]")
87118
{
88119
geom::geometry_t geom{

0 commit comments

Comments
 (0)