Skip to content

Commit 3a5ce27

Browse files
authored
More tests, more bindings, some fixes (#11)
* more bindings * more * not ready * to value * update * ready * test more geometry collection * test more * more tests * resize * more tests * more tests * more tests * more tests * fix a bug in as_numpy * init from json * handle feature id * buggy * fix * to rapidjson * update version * update release note * some fixes * there is still a bug in encoder/decoder
1 parent 2a520c5 commit 3a5ce27

File tree

10 files changed

+838
-23
lines changed

10 files changed

+838
-23
lines changed

docs/about/release-notes.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ To upgrade `pybind11-geobuf` to the latest version, use pip:
1010
pip install -U pybind11-geobuf
1111
```
1212

13+
## Version 0.0.6 (2023-03-25)
14+
15+
* More bindings, more tests
16+
* Some fixes
17+
1318
## Version 0.0.5 (2023-03-08)
1419

1520
* Add windows version

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def build_extension(self, ext):
127127
# logic and declaration, and simpler if you include description/version in a file.
128128
setup(
129129
name="pybind11_geobuf",
130-
version="0.0.5",
130+
version="0.0.6",
131131
author="tzx",
132132
author_email="dvorak4tzx@gmail.com",
133133
url="https://geobuf-cpp.readthedocs.io",

src/geobuf/geobuf.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,6 @@ std::string Encoder::encode(const mapbox::geojson::geojson &geojson)
251251
protozero::pbf_writer pbf_g{pbf, 6};
252252
writeGeometry(geometry, pbf_g);
253253
});
254-
keys.clear();
255254
return data;
256255
}
257256

@@ -361,7 +360,7 @@ void Encoder::saveKey(const std::string &key)
361360
if (keys.find(key) != keys.end()) {
362361
return;
363362
}
364-
keys.emplace(key, keys.size());
363+
keys[key] = keys.size();
365364
}
366365

367366
void Encoder::saveKey(const mapbox::feature::property_map &props)
@@ -606,7 +605,7 @@ void unpack_properties(mapbox::geojson::prop_map &properties,
606605
for (auto it = indexes.begin(); it != indexes.end();) {
607606
auto &key = keys[*it++];
608607
auto &value = values[*it++];
609-
properties.emplace(key, value);
608+
properties[key] = value;
610609
}
611610
}
612611

src/geobuf/geobuf.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
#include <protozero/pbf_builder.hpp>
77
#include <protozero/pbf_reader.hpp>
88

9+
#include <map>
10+
#include <unordered_map>
11+
912
#define MAPBOX_GEOBUF_DEFAULT_PRECISION 6
1013
#define MAPBOX_GEOBUF_DEFAULT_DIM 2
1114

@@ -99,6 +102,11 @@ struct Encoder
99102
std::string encode(const RapidjsonValue &json);
100103
bool encode(const std::string &input_path, const std::string &output_path);
101104

105+
std::map<std::string, std::uint32_t> __keys() const
106+
{
107+
return std::map<std::string, std::uint32_t>(keys.begin(), keys.end());
108+
}
109+
102110
private:
103111
void analyze(const mapbox::geojson::geojson &geojson);
104112
void analyzeGeometry(const mapbox::geojson::geometry &geometry);

src/geobuf/geojson_helpers.hpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,24 @@ inline Eigen::Map<RowVectors> as_row_vectors(mapbox::geojson::linear_ring &geom)
5252
inline Eigen::Map<RowVectors>
5353
as_row_vectors(mapbox::geojson::multi_line_string &geom)
5454
{
55+
if (geom.empty()) {
56+
return Eigen::Map<RowVectors>((double *)0, 0, 3);
57+
}
5558
return as_row_vectors(geom[0]);
5659
}
5760
inline Eigen::Map<RowVectors> as_row_vectors(mapbox::geojson::polygon &geom)
5861
{
62+
if (geom.empty() || geom.front().empty()) {
63+
return Eigen::Map<RowVectors>((double *)0, 0, 3);
64+
}
5965
return as_row_vectors(&geom[0][0].x, geom[0].size());
6066
}
6167
inline Eigen::Map<RowVectors>
6268
as_row_vectors(mapbox::geojson::multi_polygon &geom)
6369
{
70+
if (geom.empty()) {
71+
return Eigen::Map<RowVectors>((double *)0, 0, 3);
72+
}
6473
auto &shell = geom[0];
6574
return as_row_vectors(shell);
6675
}
@@ -117,18 +126,27 @@ as_row_vectors(const mapbox::geojson::linear_ring &geom)
117126
inline Eigen::Map<const RowVectors>
118127
as_row_vectors(const mapbox::geojson::multi_line_string &geom)
119128
{
129+
if (geom.empty()) {
130+
return Eigen::Map<const RowVectors>((const double *)0, 0, 3);
131+
}
120132
auto &ls = geom[0];
121133
return Eigen::Map<const RowVectors>(&ls[0].x, ls.size(), 3);
122134
}
123135
inline Eigen::Map<const RowVectors>
124136
as_row_vectors(const mapbox::geojson::polygon &geom)
125137
{
138+
if (geom.empty() || geom.front().empty()) {
139+
return Eigen::Map<const RowVectors>((const double *)0, 0, 3);
140+
}
126141
auto &shell = geom[0];
127142
return Eigen::Map<const RowVectors>(&shell[0].x, shell.size(), 3);
128143
}
129144
inline Eigen::Map<const RowVectors>
130145
as_row_vectors(const mapbox::geojson::multi_polygon &geom)
131146
{
147+
if (geom.empty()) {
148+
return Eigen::Map<const RowVectors>((const double *)0, 0, 3);
149+
}
132150
auto &poly = geom[0];
133151
return as_row_vectors(poly);
134152
}
@@ -293,6 +311,24 @@ inline void geometry_push_back(mapbox::geojson::geometry &self,
293311
geometry_push_back(self, eigen2geom(point));
294312
}
295313

314+
inline void geometry_push_back(mapbox::geojson::geometry &self,
315+
const Eigen::Ref<const MatrixXdRowMajor> &points)
316+
{
317+
self.match(
318+
[&](mapbox::geojson::multi_line_string &g) {
319+
g.push_back({});
320+
eigen2geom(points, g.back());
321+
},
322+
[&](mapbox::geojson::polygon &g) {
323+
g.push_back({});
324+
eigen2geom(points, g.back());
325+
},
326+
[&](auto &g) {
327+
std::cerr << "geometry_push_back not handled for this type: "
328+
<< geometry_type(g) << std::endl;
329+
});
330+
}
331+
296332
inline void geometry_push_back(mapbox::geojson::geometry &self,
297333
const mapbox::geojson::geometry &geom)
298334
{

src/geobuf/pybind11_helpers.hpp

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ using RapidjsonAllocator = mapbox::geojson::rapidjson_allocator;
2929
using RapidjsonDocument = mapbox::geojson::rapidjson_document;
3030
using geojson_value = mapbox::geojson::value;
3131

32-
inline RapidjsonValue py_int_to_rapidjson(const py::handle &obj)
32+
inline RapidjsonValue __py_int_to_rapidjson(const py::handle &obj)
3333
{
3434
try {
3535
auto num = obj.cast<int64_t>();
@@ -60,7 +60,7 @@ inline RapidjsonValue to_rapidjson(const py::handle &obj,
6060
return RapidjsonValue(obj.cast<bool>());
6161
}
6262
if (py::isinstance<py::int_>(obj)) {
63-
return py_int_to_rapidjson(obj);
63+
return __py_int_to_rapidjson(obj);
6464
}
6565
if (py::isinstance<py::float_>(obj)) {
6666
return RapidjsonValue(obj.cast<double>());
@@ -276,7 +276,7 @@ inline py::object to_python(const mapbox::geojson::geometry &obj)
276276
[&](const mapbox::geojson::geometry_collection &g) {
277277
py::list geometries;
278278
for (auto &gg : g) {
279-
geometries.append(to_python(mapbox::geojson::geometry(gg)));
279+
geometries.append(to_python(gg));
280280
}
281281
ret["geometries"] = geometries;
282282
},
@@ -295,6 +295,44 @@ inline py::object to_python(const mapbox::geojson::geometry &obj)
295295
return ret;
296296
}
297297

298+
inline py::object to_python(const mapbox::geojson::geometry_collection &obj)
299+
{
300+
return to_python(mapbox::geojson::geometry{obj});
301+
}
302+
303+
inline py::object to_python(const mapbox::geojson::identifier &id)
304+
{
305+
py::object ret = py::none();
306+
// null_value_t, uint64_t, int64_t, double, std::string
307+
id.match([&](mapbox::feature::null_value_t v) {},
308+
[&](uint64_t v) { ret = py::int_(v); },
309+
[&](int64_t v) { ret = py::int_(v); },
310+
[&](double v) { ret = py::float_(v); },
311+
[&](const std::string &v) { ret = py::str(v); },
312+
[&](const auto &) -> void {});
313+
return ret;
314+
}
315+
316+
inline mapbox::geojson::identifier to_feature_id(const py::object &obj)
317+
{
318+
if (obj.ptr() == nullptr || obj.is_none()) {
319+
return {};
320+
}
321+
if (py::isinstance<py::int_>(obj)) {
322+
auto val = obj.cast<long long>();
323+
if (val < 0) {
324+
return int64_t(val);
325+
} else {
326+
return uint64_t(val);
327+
}
328+
} else if (py::isinstance<py::float_>(obj)) {
329+
return obj.cast<double>();
330+
} else if (py::isinstance<py::str>(obj)) {
331+
return obj.cast<std::string>();
332+
}
333+
return {};
334+
}
335+
298336
inline py::object to_python(const mapbox::geojson::feature &f)
299337
{
300338
py::dict ret;

src/geobuf/rapidjson_helpers.hpp

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#ifndef CUBAO_RAPIDJSON_HELPERS_HPP
22
#define CUBAO_RAPIDJSON_HELPERS_HPP
33

4+
#include <mapbox/geojson.hpp>
45
#include <mapbox/geojson/rapidjson.hpp>
6+
#include <mapbox/geojson/value.hpp>
57

68
#include "rapidjson/error/en.h"
79
#include "rapidjson/filereadstream.h"
@@ -178,6 +180,98 @@ inline int __len__(const RapidjsonValue &self)
178180
}
179181
return 0;
180182
}
183+
184+
struct to_value
185+
{
186+
RapidjsonAllocator &allocator;
187+
188+
RapidjsonValue operator()(mapbox::geojson::null_value_t)
189+
{
190+
RapidjsonValue result;
191+
result.SetNull();
192+
return result;
193+
}
194+
195+
RapidjsonValue operator()(bool t)
196+
{
197+
RapidjsonValue result;
198+
result.SetBool(t);
199+
return result;
200+
}
201+
202+
RapidjsonValue operator()(int64_t t)
203+
{
204+
RapidjsonValue result;
205+
result.SetInt64(t);
206+
return result;
207+
}
208+
209+
RapidjsonValue operator()(uint64_t t)
210+
{
211+
RapidjsonValue result;
212+
result.SetUint64(t);
213+
return result;
214+
}
215+
216+
RapidjsonValue operator()(double t)
217+
{
218+
RapidjsonValue result;
219+
result.SetDouble(t);
220+
return result;
221+
}
222+
223+
RapidjsonValue operator()(const std::string &t)
224+
{
225+
RapidjsonValue result;
226+
result.SetString(t.data(), rapidjson::SizeType(t.size()), allocator);
227+
return result;
228+
}
229+
230+
RapidjsonValue operator()(const std::vector<mapbox::geojson::value> &array)
231+
{
232+
RapidjsonValue result;
233+
result.SetArray();
234+
for (const auto &item : array) {
235+
result.PushBack(mapbox::geojson::value::visit(item, *this),
236+
allocator);
237+
}
238+
return result;
239+
}
240+
241+
RapidjsonValue operator()(
242+
const std::unordered_map<std::string, mapbox::geojson::value> &map)
243+
{
244+
RapidjsonValue result;
245+
result.SetObject();
246+
for (const auto &property : map) {
247+
result.AddMember(
248+
RapidjsonValue(property.first.data(),
249+
rapidjson::SizeType(property.first.size()),
250+
allocator),
251+
mapbox::geojson::value::visit(property.second, *this),
252+
allocator);
253+
}
254+
return result;
255+
}
256+
};
257+
258+
inline RapidjsonValue to_rapidjson(const mapbox::geojson::value &json,
259+
RapidjsonAllocator &allocator)
260+
{
261+
return mapbox::geojson::value::visit(json, cubao::to_value{allocator});
262+
}
263+
264+
inline RapidjsonValue to_rapidjson(const mapbox::geojson::value &json)
265+
{
266+
RapidjsonAllocator allocator;
267+
return to_rapidjson(json, allocator);
268+
}
269+
270+
// inline mapbox::geojson::value to_geojson_value(const RapidjsonValue &json)
271+
// {
272+
// return mapbox::geojson::convert<mapbox::geojson::value>(json);
273+
// }
274+
181275
} // namespace cubao
182276

183277
#endif

src/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ PYBIND11_MODULE(_pybind11_geobuf, m)
141141
py::overload_cast<const std::string &, const std::string &>(
142142
&Encoder::encode),
143143
py::kw_only(), "geojson"_a, "geobuf"_a)
144+
.def("keys", &Encoder::__keys)
144145
//
145146
;
146147

0 commit comments

Comments
 (0)