Skip to content

Commit 9a2539e

Browse files
committed
Complete WKB writer implementation with support for all types
1 parent e51b546 commit 9a2539e

File tree

2 files changed

+108
-29
lines changed

2 files changed

+108
-29
lines changed

src/geom.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,16 @@ class geometry_t
258258

259259
} // namespace geom
260260

261+
// This magic is used for visiting geometries. For an explanation see for
262+
// instance here:
263+
// https://arne-mertz.de/2018/05/overload-build-a-variant-visitor-on-the-fly/
264+
template <class... Ts>
265+
struct overloaded : Ts...
266+
{
267+
using Ts::operator()...;
268+
};
269+
270+
template <class... Ts>
271+
overloaded(Ts...) -> overloaded<Ts...>;
272+
261273
#endif // OSM2PGSQL_GEOM_HPP

src/wkb.cpp

Lines changed: 96 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ void write_length(std::string *data, std::size_t length)
8181
str_push(data, static_cast<uint32_t>(length));
8282
}
8383

84+
void write_point(std::string *data, geom::point_t const &geom,
85+
uint32_t srid = 0)
86+
{
87+
assert(data);
88+
89+
write_header(data, wkb_point, srid);
90+
str_push(data, geom.x());
91+
str_push(data, geom.y());
92+
}
93+
8494
void write_points(std::string *data, geom::point_list_t const &points)
8595
{
8696
write_length(data, points.size());
@@ -91,7 +101,7 @@ void write_points(std::string *data, geom::point_list_t const &points)
91101
}
92102

93103
void write_linestring(std::string *data, geom::linestring_t const &geom,
94-
uint32_t srid)
104+
uint32_t srid = 0)
95105
{
96106
assert(data);
97107

@@ -100,7 +110,7 @@ void write_linestring(std::string *data, geom::linestring_t const &geom,
100110
}
101111

102112
void write_polygon(std::string *data, geom::polygon_t const &geom,
103-
uint32_t srid)
113+
uint32_t srid = 0)
104114
{
105115
assert(data);
106116

@@ -112,6 +122,77 @@ void write_polygon(std::string *data, geom::polygon_t const &geom,
112122
}
113123
}
114124

125+
void write_multipoint(std::string *data, geom::multipoint_t const &geom,
126+
uint32_t srid = 0)
127+
{
128+
assert(data);
129+
130+
write_header(data, wkb_multi_point, srid);
131+
write_length(data, geom.num_geometries());
132+
133+
for (auto const &point : geom) {
134+
write_point(data, point);
135+
}
136+
}
137+
138+
void write_multilinestring(std::string *data,
139+
geom::multilinestring_t const &geom,
140+
uint32_t srid = 0)
141+
{
142+
assert(data);
143+
144+
write_header(data, wkb_multi_line, srid);
145+
write_length(data, geom.num_geometries());
146+
147+
for (auto const &line : geom) {
148+
write_linestring(data, line);
149+
}
150+
}
151+
152+
void write_multipolygon(std::string *data, geom::multipolygon_t const &geom,
153+
uint32_t srid = 0)
154+
{
155+
assert(data);
156+
157+
write_header(data, wkb_multi_polygon, srid);
158+
write_length(data, geom.num_geometries());
159+
160+
for (auto const &polygon : geom) {
161+
write_polygon(data, polygon);
162+
}
163+
}
164+
165+
void write_collection(std::string *data, geom::collection_t const &geom,
166+
uint32_t srid = 0)
167+
{
168+
assert(data);
169+
170+
write_header(data, wkb_collection, srid);
171+
write_length(data, geom.num_geometries());
172+
173+
for (auto const &item : geom) {
174+
item.visit(overloaded{
175+
[&](geom::nullgeom_t const & /*input*/) {},
176+
[&](geom::point_t const &input) { write_point(data, input); },
177+
[&](geom::linestring_t const &input) {
178+
write_linestring(data, input);
179+
},
180+
[&](geom::polygon_t const &input) { write_polygon(data, input); },
181+
[&](geom::multipoint_t const &input) {
182+
write_multipoint(data, input);
183+
},
184+
[&](geom::multilinestring_t const &input) {
185+
write_multilinestring(data, input);
186+
},
187+
[&](geom::multipolygon_t const &input) {
188+
write_multipolygon(data, input);
189+
},
190+
[&](geom::collection_t const &input) {
191+
write_collection(data, input);
192+
}});
193+
}
194+
}
195+
115196
class make_ewkb_visitor
116197
{
117198
public:
@@ -132,9 +213,7 @@ class make_ewkb_visitor
132213
std::string data;
133214

134215
data.reserve(size);
135-
write_header(&data, wkb_point, m_srid);
136-
str_push(&data, geom.x());
137-
str_push(&data, geom.y());
216+
write_point(&data, geom, m_srid);
138217

139218
assert(data.size() == size);
140219

@@ -150,7 +229,7 @@ class make_ewkb_visitor
150229
data.reserve(2 * 13 + geom.size() * (2 * 8));
151230
write_header(&data, wkb_multi_line, m_srid);
152231
write_length(&data, 1);
153-
write_linestring(&data, geom, 0);
232+
write_linestring(&data, geom);
154233
} else {
155234
// 13 byte header plus n sets of coordinates
156235
data.reserve(13 + geom.size() * (2 * 8));
@@ -167,52 +246,40 @@ class make_ewkb_visitor
167246
if (m_ensure_multi) {
168247
write_header(&data, wkb_multi_polygon, m_srid);
169248
write_length(&data, 1);
170-
write_polygon(&data, geom, 0);
249+
write_polygon(&data, geom);
171250
} else {
172251
write_polygon(&data, geom, m_srid);
173252
}
174253

175254
return data;
176255
}
177256

178-
std::string operator()(geom::multipoint_t const & /*geom*/) const
257+
std::string operator()(geom::multipoint_t const &geom) const
179258
{
180-
assert(false);
181-
return {}; // XXX not used yet, no implementation
259+
std::string data;
260+
write_multipoint(&data, geom, m_srid);
261+
return data;
182262
}
183263

184264
std::string operator()(geom::multilinestring_t const &geom) const
185265
{
186266
std::string data;
187-
188-
write_header(&data, wkb_multi_line, m_srid);
189-
write_length(&data, geom.num_geometries());
190-
191-
for (auto const &line : geom) {
192-
write_linestring(&data, line, 0);
193-
}
194-
267+
write_multilinestring(&data, geom, m_srid);
195268
return data;
196269
}
197270

198271
std::string operator()(geom::multipolygon_t const &geom) const
199272
{
200273
std::string data;
201-
202-
write_header(&data, wkb_multi_polygon, m_srid);
203-
write_length(&data, geom.num_geometries());
204-
205-
for (auto const &polygon : geom) {
206-
write_polygon(&data, polygon, 0);
207-
}
208-
274+
write_multipolygon(&data, geom, m_srid);
209275
return data;
210276
}
211277

212-
std::string operator()(geom::collection_t const & /*geom*/) const
278+
std::string operator()(geom::collection_t const &geom) const
213279
{
214-
assert(false);
215-
return {}; // XXX not used yet, no implementation
280+
std::string data;
281+
write_collection(&data, geom, m_srid);
282+
return data;
216283
}
217284

218285
private:

0 commit comments

Comments
 (0)