Skip to content

Commit 7b159ac

Browse files
authored
More tests, more bindings; several fixes (#9)
* always export z, more tests * more tests * not ready * update * fix * lint code * update * clear is not working?? * clear works * need to fix g1[idx] * add __len___ to Point * add push_back(line) * okay * fix * LinearRing * gc len * clean code * python value semantic * fix clear * get/set item * raise Exception if not Nx2 or Nx3 * more * more * more * need to fix feature * not ready * sort keys * set and copy * fix empty bug * test bytes
1 parent 2fbb6e8 commit 7b159ac

File tree

7 files changed

+878
-192
lines changed

7 files changed

+878
-192
lines changed

data/sample1.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
22
"type": "FeatureCollection",
33
"key": "value",
4-
"shit me": 42,
54
"features": [
65
{
76
"type": "Feature",

src/geobuf/geojson_helpers.hpp

Lines changed: 132 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -169,68 +169,67 @@ inline std::string geometry_type(const mapbox::geojson::geometry &self)
169169
[](const auto &g) -> std::string { return "None"; });
170170
}
171171

172-
inline void eigen2geom(const Eigen::MatrixXd &mat,
173-
std::vector<mapbox::geojson::point> &points)
174-
{
175-
if (mat.rows() == 0) {
176-
points.clear();
177-
return;
178-
}
179-
if (mat.cols() != 2 && mat.cols() != 3) {
180-
return;
181-
}
182-
points.resize(mat.rows());
183-
Eigen::Map<RowVectors> M(&points[0].x, points.size(), 3);
184-
M.leftCols(mat.cols()) = mat;
185-
}
186-
187172
using MatrixXdRowMajor =
188173
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
189174

190-
inline void eigen2geom(Eigen::Ref<const MatrixXdRowMajor> mat,
175+
inline void eigen2geom(const Eigen::Ref<const MatrixXdRowMajor> &mat,
191176
std::vector<mapbox::geojson::point> &points)
192177
{
193178
if (mat.rows() == 0) {
194179
points.clear();
195180
return;
196181
}
197-
if (mat.cols() != 2 && mat.cols() != 3) {
182+
const int cols = mat.cols();
183+
if (cols != 2 && cols != 3) {
184+
throw std::invalid_argument(
185+
"matrix shape expected to be Nx2 or Nx3, actual=" +
186+
std::to_string(mat.rows()) + "x" + std::to_string(cols));
198187
return;
199188
}
200189
points.resize(mat.rows());
201190
Eigen::Map<RowVectors> M(&points[0].x, points.size(), 3);
202191
M.leftCols(mat.cols()) = mat;
192+
if (cols == 2) {
193+
M.col(2).setZero();
194+
}
195+
}
196+
197+
inline mapbox::geojson::point eigen2geom(const Eigen::VectorXd &xyz)
198+
{
199+
return {xyz[0], xyz[1], xyz.size() > 2 ? xyz[2] : 0.0};
203200
}
204201

205-
inline void eigen2geom(Eigen::Ref<const MatrixXdRowMajor> points,
202+
inline void eigen2geom(const Eigen::Ref<const MatrixXdRowMajor> &points,
206203
mapbox::geojson::point &g)
207204
{
208-
Eigen::Vector3d::Map(&g.x) = points.row(0).transpose();
205+
g.x = points(0, 0);
206+
g.y = points(0, 1);
207+
g.z = points.cols() > 2 ? points(0, 2) : 0.0;
209208
}
210209

211-
inline void eigen2geom(Eigen::Ref<const MatrixXdRowMajor> points,
210+
inline void eigen2geom(const Eigen::Ref<const MatrixXdRowMajor> &points,
212211
mapbox::geojson::multi_line_string &g)
213212
{
214213
g.resize(1);
215214
eigen2geom(points, g[0]);
216215
}
217216

218-
inline void eigen2geom(Eigen::Ref<const MatrixXdRowMajor> points,
217+
inline void eigen2geom(const Eigen::Ref<const MatrixXdRowMajor> &points,
219218
mapbox::geojson::polygon &g)
220219
{
221220
g.resize(1);
222221
eigen2geom(points, g[0]);
223222
}
224223

225-
inline void eigen2geom(Eigen::Ref<const MatrixXdRowMajor> points,
224+
inline void eigen2geom(const Eigen::Ref<const MatrixXdRowMajor> &points,
226225
mapbox::geojson::multi_polygon &g)
227226
{
228227
g.resize(1);
229228
g[0].resize(1);
230229
eigen2geom(points, g[0][0]);
231230
}
232231

233-
inline void eigen2geom(Eigen::Ref<const MatrixXdRowMajor> points,
232+
inline void eigen2geom(const Eigen::Ref<const MatrixXdRowMajor> &points,
234233
mapbox::geojson::geometry &geom)
235234
{
236235
geom.match(
@@ -240,12 +239,23 @@ inline void eigen2geom(Eigen::Ref<const MatrixXdRowMajor> points,
240239
[&](mapbox::geojson::multi_point &g) { eigen2geom(points, g); },
241240
[&](mapbox::geojson::multi_line_string &g) { eigen2geom(points, g); },
242241
[&](mapbox::geojson::multi_polygon &g) { eigen2geom(points, g); },
242+
[&](mapbox::geojson::geometry_collection &g) {
243+
g.resize(1);
244+
eigen2geom(points, g[0]);
245+
},
243246
[&](auto &g) -> void {
244247
std::cerr << "eigen2geom not handled for this type: "
245248
<< geometry_type(g) << std::endl;
246249
});
247250
}
248251

252+
inline void eigen2geom(const Eigen::Ref<const MatrixXdRowMajor> &points,
253+
mapbox::geojson::geometry_collection &g)
254+
{
255+
g.resize(1);
256+
eigen2geom(points, g[0]);
257+
}
258+
249259
inline std::string get_type(const mapbox::geojson::value &self)
250260
{
251261
return self.match(
@@ -264,44 +274,134 @@ inline void geometry_push_back(mapbox::geojson::geometry &self,
264274
{
265275
self.match([&](mapbox::geojson::multi_point &g) { g.push_back(point); },
266276
[&](mapbox::geojson::line_string &g) { g.push_back(point); },
267-
[&](auto &) {
268-
// TODO, log
277+
[&](mapbox::geojson::multi_line_string &g) {
278+
g.back().push_back(point);
279+
},
280+
[&](mapbox::geojson::polygon &g) { g.back().push_back(point); },
281+
[&](mapbox::geojson::multi_polygon &g) {
282+
g.back().back().push_back(point);
283+
},
284+
[&](auto &g) {
285+
std::cerr << "geometry_push_back not handled for this type: "
286+
<< geometry_type(g) << std::endl;
269287
});
270288
}
271289

272290
inline void geometry_push_back(mapbox::geojson::geometry &self,
273291
const Eigen::VectorXd &point)
274292
{
275-
auto geom = mapbox::geojson::point(point[0], point[1],
276-
point.size() > 2 ? point[2] : 0.0);
277-
geometry_push_back(self, geom);
293+
geometry_push_back(self, eigen2geom(point));
278294
}
279295

280296
inline void geometry_push_back(mapbox::geojson::geometry &self,
281297
const mapbox::geojson::geometry &geom)
282298
{
283299
self.match(
284300
[&](mapbox::geojson::geometry_collection &g) { g.push_back(geom); },
285-
[&](auto &) {});
301+
[&](auto &g) {
302+
std::cerr << "geometry_push_back(geom) not handled for this type: "
303+
<< geometry_type(g) << std::endl;
304+
});
286305
}
287306

288307
inline void geometry_pop_back(mapbox::geojson::geometry &self)
289308
{
290-
// TODO
309+
self.match([&](mapbox::geojson::multi_point &g) { g.pop_back(); },
310+
[&](mapbox::geojson::line_string &g) { g.pop_back(); },
311+
[&](mapbox::geojson::multi_line_string &g) {
312+
g.back().pop_back();
313+
// not g.pop_back()
314+
},
315+
[&](mapbox::geojson::polygon &g) {
316+
g.back().pop_back();
317+
// not g.pop_back()
318+
},
319+
[&](mapbox::geojson::multi_polygon &g) {
320+
g.back().back().pop_back();
321+
// not g.pop_back()
322+
},
323+
[&](auto &g) {
324+
std::cerr
325+
<< "geometry_pop_back() not handled for this type: "
326+
<< geometry_type(g) << std::endl;
327+
});
291328
}
292329
inline void geometry_clear(mapbox::geojson::geometry &self)
293330
{
294-
// TODO
331+
self.match([&](mapbox::geojson::multi_point &g) { g.clear(); },
332+
[&](mapbox::geojson::line_string &g) { g.clear(); },
333+
[&](mapbox::geojson::multi_line_string &g) {
334+
g.clear();
335+
// not g.back().clear();
336+
},
337+
[&](mapbox::geojson::polygon &g) {
338+
g.clear();
339+
// not g.back().clear();
340+
},
341+
[&](mapbox::geojson::multi_polygon &g) {
342+
g.clear();
343+
// not g.back().back().clear();
344+
},
345+
[&](mapbox::geojson::point &g) { g.x = g.y = g.z = 0.0; },
346+
[&](mapbox::geojson::geometry_collection &g) { g.clear(); },
347+
[&](auto &g) {
348+
std::cerr << "geometry_clear() not handled for this type: "
349+
<< geometry_type(g) << std::endl;
350+
});
295351
}
296352

297-
inline void clear_geojson_value(mapbox::geojson::value &self)
353+
inline void geojson_value_clear(mapbox::geojson::value &self)
298354
{
299355
self.match([](mapbox::geojson::value::array_type &arr) { arr.clear(); },
300356
[](mapbox::geojson::value::object_type &obj) { obj.clear(); },
301357
[](bool &b) { b = false; }, [](uint64_t &i) { i = 0UL; },
302358
[](int64_t &i) { i = 0; }, [](double &d) { d = 0.0; },
303359
[](std::string &str) { str.clear(); }, [](auto &) -> void {});
304360
}
361+
362+
inline bool __bool__(const mapbox::geojson::value &self)
363+
{
364+
return self.match(
365+
[](const mapbox::geojson::value::object_type &obj) {
366+
return !obj.empty();
367+
},
368+
[](const mapbox::geojson::value::array_type &arr) {
369+
return !arr.empty();
370+
},
371+
[](const bool &b) { return b; },
372+
[](const uint64_t &i) { return i != 0; },
373+
[](const int64_t &i) { return i != 0; },
374+
[](const double &d) { return d != 0; },
375+
[](const std::string &s) { return !s.empty(); },
376+
[](const mapbox::geojson::null_value_t &) { return false; },
377+
[](auto &v) -> bool { return false; });
378+
}
379+
380+
inline int __len__(const mapbox::geojson::value &self)
381+
{
382+
return self.match(
383+
[](const mapbox::geojson::value::array_type &arr) {
384+
return arr.size();
385+
},
386+
[](const mapbox::geojson::value::object_type &obj) {
387+
return obj.size();
388+
},
389+
[](auto &) -> int { return 0; });
390+
}
391+
inline int __len__(mapbox::geojson::geometry &self)
392+
{
393+
return self.match(
394+
[](mapbox::geojson::point &g) { return 3; },
395+
[](mapbox::geojson::multi_point &g) { return g.size(); },
396+
[](mapbox::geojson::line_string &g) { return g.size(); },
397+
[](mapbox::geojson::linear_ring &g) { return g.size(); },
398+
[](mapbox::geojson::multi_line_string &g) { return g.size(); },
399+
[](mapbox::geojson::polygon &g) { return g.size(); },
400+
[](mapbox::geojson::multi_polygon &g) { return g.size(); },
401+
[](mapbox::geojson::geometry_collection &g) { return g.size(); },
402+
[](auto &) -> int { return 0; });
403+
}
404+
305405
} // namespace cubao
306406

307407
#endif

src/geobuf/rapidjson_helpers.hpp

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,33 @@ template <typename T> RapidjsonValue int_to_rapidjson(T const &num)
4848
}
4949
}
5050

51+
inline void sort_keys_inplace(RapidjsonValue &json)
52+
{
53+
if (json.IsArray()) {
54+
for (auto &e : json.GetArray()) {
55+
sort_keys_inplace(e);
56+
}
57+
} else if (json.IsObject()) {
58+
auto obj = json.GetObject();
59+
// https://rapidjson.docsforge.com/master/sortkeys.cpp/
60+
std::sort(obj.MemberBegin(), obj.MemberEnd(), [](auto &lhs, auto &rhs) {
61+
return strcmp(lhs.name.GetString(), rhs.name.GetString()) < 0;
62+
});
63+
for (auto &kv : obj) {
64+
sort_keys_inplace(kv.value);
65+
}
66+
}
67+
}
68+
69+
inline RapidjsonValue sort_keys(const RapidjsonValue &json)
70+
{
71+
RapidjsonAllocator allocator;
72+
RapidjsonValue copy;
73+
copy.CopyFrom(json, allocator);
74+
sort_keys_inplace(copy);
75+
return copy;
76+
}
77+
5178
inline RapidjsonValue load_json(const std::string &path)
5279
{
5380
FILE *fp = fopen(path.c_str(), "rb");
@@ -62,7 +89,7 @@ inline RapidjsonValue load_json(const std::string &path)
6289
return RapidjsonValue{std::move(d.Move())};
6390
}
6491
inline bool dump_json(const std::string &path, const RapidjsonValue &json,
65-
bool indent = false)
92+
bool indent = false, bool sort_keys = false)
6693
{
6794
FILE *fp = fopen(path.c_str(), "wb");
6895
if (!fp) {
@@ -74,10 +101,18 @@ inline bool dump_json(const std::string &path, const RapidjsonValue &json,
74101
FileWriteStream os(fp, writeBuffer, sizeof(writeBuffer));
75102
if (indent) {
76103
PrettyWriter<FileWriteStream> writer(os);
77-
json.Accept(writer);
104+
if (sort_keys) {
105+
cubao::sort_keys(json).Accept(writer);
106+
} else {
107+
json.Accept(writer);
108+
}
78109
} else {
79110
Writer<FileWriteStream> writer(os);
80-
json.Accept(writer);
111+
if (sort_keys) {
112+
cubao::sort_keys(json).Accept(writer);
113+
} else {
114+
json.Accept(writer);
115+
}
81116
}
82117
fclose(fp);
83118
return true;
@@ -95,8 +130,12 @@ inline RapidjsonValue loads(const std::string &json)
95130
}
96131
return RapidjsonValue{std::move(d.Move())};
97132
}
98-
inline std::string dumps(const RapidjsonValue &json, bool indent = false)
133+
inline std::string dumps(const RapidjsonValue &json, bool indent = false,
134+
bool sort_keys = false)
99135
{
136+
if (sort_keys) {
137+
return dumps(cubao::sort_keys(json), indent, !sort_keys);
138+
}
100139
rapidjson::StringBuffer buffer;
101140
if (indent) {
102141
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);

0 commit comments

Comments
 (0)