Skip to content

Commit 499cddf

Browse files
authored
deduplicate coords, round coords; more bindings, more tests (#13)
* round coords * round coords * fix rounding * round for all geometry types * more tests * more tests * TODO, should use js.round * remove duplicates * deduplicate * integrate deduplicate * add sample data * load json * add load/dump * add load/dump to GeoJSON * handle no such file * push_back for geometry collection * push back polygon * test round geojson * update docs
1 parent 4c9f5c5 commit 499cddf

File tree

8 files changed

+803
-23
lines changed

8 files changed

+803
-23
lines changed

data/feature.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"type": "Feature",
3+
"id": 234,
4+
"properties": {
5+
"string": "string",
6+
"int": 42,
7+
"int2": -101,
8+
"double": 3.141592653,
9+
"list": ["a", "list", "is", "a", "list"],
10+
"dict": {"key": 42, "value": 3.14}
11+
},
12+
"geometry": {
13+
"coordinates": [
14+
[120.40317479950272, 31.416966084052177, 1.111111],
15+
[120.28451900911591, 31.30578266928819, 2.22],
16+
[120.35592249359615, 31.21781895672254, 3.3333333333333],
17+
[120.67093786630113, 31.299502266522722, 4.4]
18+
],
19+
"type": "LineString",
20+
"extra_key": "extra_value"
21+
},
22+
"my_key": "my_value"
23+
}

data/feature_collection.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"type": "FeatureCollection",
3+
"features": [
4+
{
5+
"type": "Feature",
6+
"id": 234,
7+
"properties": {
8+
"string": "string",
9+
"int": 42,
10+
"int2": -101,
11+
"double": 3.141592653,
12+
"list": ["a", "list", "is", "a", "list"],
13+
"dict": {"key": 42, "value": 3.14}
14+
},
15+
"geometry": {
16+
"coordinates": [
17+
[120.40317479950272, 31.416966084052177, 1.111111],
18+
[120.28451900911591, 31.30578266928819, 2.22],
19+
[120.35592249359615, 31.21781895672254, 3.3333333333333],
20+
[120.67093786630113, 31.299502266522722, 4.4]
21+
],
22+
"type": "LineString",
23+
"extra_key": "extra_value"
24+
},
25+
"my_key": "my_value"
26+
}
27+
],
28+
"my_key": "this is fc"
29+
}

data/geometry.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"coordinates": [
3+
[120.40317479950272, 31.416966084052177, 1.111111],
4+
[120.28451900911591, 31.30578266928819, 2.22],
5+
[120.35592249359615, 31.21781895672254, 3.3333333333333],
6+
[120.67093786630113, 31.299502266522722, 4.4]
7+
],
8+
"type": "LineString",
9+
"extra_key": "extra_value"
10+
}

docs/about/release-notes.md

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

13+
## Version 0.0.7 (2023-03-26)
14+
15+
* More bindings, more tests
16+
1317
## Version 0.0.6 (2023-03-25)
1418

1519
* More bindings, more tests

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.6",
130+
version="0.0.7",
131131
author="tzx",
132132
author_email="dvorak4tzx@gmail.com",
133133
url="https://geobuf-cpp.readthedocs.io",

src/geobuf/geojson_helpers.hpp

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <Eigen/Core>
1111
#include <iostream>
1212
#include <mapbox/geojson.hpp>
13+
#include <type_traits>
1314

1415
static_assert(sizeof(mapbox::geojson::point) == sizeof(Eigen::Vector3d),
1516
"mapbox::geojson::point should be double*3 (xyz instead of xy)");
@@ -438,6 +439,189 @@ inline int __len__(mapbox::geojson::geometry &self)
438439
[](auto &) -> int { return 0; });
439440
}
440441

442+
inline double round_coords(double value, double scale)
443+
{
444+
// rounding is hard, we just use the most simple implementation
445+
// see
446+
// - https://github.com/Tencent/rapidjson/issues/362
447+
// - https://en.cppreference.com/w/cpp/numeric/math/round
448+
// rounding halfway cases away from zero
449+
// -
450+
// https://stackoverflow.com/questions/485525/round-for-float-in-c/24348037#24348037
451+
// also note that, javascript Math.round differs from C++ round
452+
// e.g. std::round(-0.5) => -1.0
453+
// Math.round(-0.5) => -0.0
454+
return std::round(value * scale) / scale;
455+
// TODO, all should use Math.round!!!
456+
// Math.round equivalent:
457+
// std::floor(value * scale + 0.5) / scale
458+
}
459+
460+
inline void round_coords(mapbox::geojson::point &xyz,
461+
const Eigen::Vector3d &scale)
462+
{
463+
xyz.x = round_coords(xyz.x, scale[0]);
464+
xyz.y = round_coords(xyz.y, scale[1]);
465+
xyz.z = round_coords(xyz.z, scale[2]);
466+
}
467+
468+
inline void round_coords(std::vector<mapbox::geojson::point> &coords,
469+
const Eigen::Vector3d &scale)
470+
{
471+
for (auto &pt : coords) {
472+
round_coords(pt, scale);
473+
}
474+
}
475+
476+
inline void round_coords(mapbox::geojson::geometry &g, const Eigen::Vector3d &s)
477+
{
478+
return g.match(
479+
[&](mapbox::geojson::point &g) { return round_coords(g, s); },
480+
[&](mapbox::geojson::multi_point &g) { round_coords(g, s); },
481+
[&](mapbox::geojson::line_string &g) { round_coords(g, s); },
482+
[&](mapbox::geojson::linear_ring &g) { round_coords(g, s); },
483+
[&](mapbox::geojson::multi_line_string &gg) {
484+
for (auto &g : gg) {
485+
round_coords(g, s);
486+
}
487+
},
488+
[&](mapbox::geojson::polygon &gg) {
489+
for (auto &g : gg) {
490+
round_coords(g, s);
491+
}
492+
},
493+
[&](mapbox::geojson::multi_polygon &ggg) {
494+
for (auto &gg : ggg) {
495+
for (auto &g : gg) {
496+
round_coords(g, s);
497+
}
498+
}
499+
},
500+
[&](mapbox::geojson::geometry_collection &gc) {
501+
for (auto &g : gc) {
502+
round_coords(g, s);
503+
}
504+
},
505+
[](auto &) {});
506+
}
507+
508+
template <typename T>
509+
inline void round_coords(T &xyz, int lon = 8, int lat = 8, int alt = 3)
510+
{
511+
Eigen::Vector3d scale_up(std::pow(10, lon), //
512+
std::pow(10, lat), //
513+
std::pow(10, alt));
514+
round_coords(xyz, scale_up);
515+
}
516+
517+
inline bool deduplicate_xyz(std::vector<mapbox::geojson::point> &geom)
518+
{
519+
auto itr = std::unique(
520+
geom.begin(), geom.end(),
521+
[](const auto &prev, const auto &curr) { return prev == curr; });
522+
if (itr == geom.end()) {
523+
return false;
524+
}
525+
geom.erase(itr, geom.end());
526+
return true;
527+
}
528+
inline bool deduplicate_xyz(mapbox::geojson::empty &geom)
529+
{
530+
return false; // dummy
531+
}
532+
inline bool deduplicate_xyz(mapbox::geojson::point &geom)
533+
{
534+
return false; // dummy
535+
}
536+
inline bool deduplicate_xyz(mapbox::geojson::multi_point &geom)
537+
{
538+
return deduplicate_xyz((std::vector<mapbox::geojson::point> &)geom);
539+
}
540+
inline bool deduplicate_xyz(mapbox::geojson::line_string &geom)
541+
{
542+
return deduplicate_xyz((std::vector<mapbox::geojson::point> &)geom);
543+
}
544+
inline bool deduplicate_xyz(mapbox::geojson::multi_line_string &geom)
545+
{
546+
bool removed = false;
547+
for (auto &g : geom) {
548+
removed |= deduplicate_xyz(g);
549+
}
550+
return removed;
551+
}
552+
inline bool deduplicate_xyz(mapbox::geojson::linear_ring &geom)
553+
{
554+
return deduplicate_xyz((std::vector<mapbox::geojson::point> &)geom);
555+
}
556+
inline bool deduplicate_xyz(mapbox::geojson::polygon &geom)
557+
{
558+
bool removed = false;
559+
for (auto &g : geom) {
560+
removed |= deduplicate_xyz(g);
561+
}
562+
return removed;
563+
}
564+
inline bool deduplicate_xyz(mapbox::geojson::multi_polygon &geom)
565+
{
566+
bool removed = false;
567+
for (auto &g : geom) {
568+
removed |= deduplicate_xyz(g);
569+
}
570+
return removed;
571+
}
572+
573+
inline bool deduplicate_xyz(mapbox::geojson::geometry &geom)
574+
{
575+
return geom.match(
576+
[&](mapbox::geojson::multi_point &g) { return deduplicate_xyz(g); },
577+
[&](mapbox::geojson::line_string &g) { return deduplicate_xyz(g); },
578+
[&](mapbox::geojson::linear_ring &g) { return deduplicate_xyz(g); },
579+
[&](mapbox::geojson::multi_line_string &g) {
580+
return deduplicate_xyz(g);
581+
},
582+
[&](mapbox::geojson::polygon &g) { return deduplicate_xyz(g); },
583+
[&](mapbox::geojson::multi_polygon &g) { return deduplicate_xyz(g); },
584+
[&](mapbox::geojson::geometry_collection &gc) {
585+
bool removed = false;
586+
for (auto &g : gc) {
587+
removed |= deduplicate_xyz(g);
588+
}
589+
return removed;
590+
},
591+
[](auto &) -> bool { return false; });
592+
}
593+
inline bool deduplicate_xyz(mapbox::geojson::geometry_collection &geom)
594+
{
595+
bool removed = false;
596+
for (auto &g : geom) {
597+
removed |= deduplicate_xyz(g);
598+
}
599+
return removed;
600+
}
601+
602+
inline bool deduplicate_xyz(mapbox::geojson::feature &f)
603+
{
604+
return deduplicate_xyz(f.geometry);
605+
}
606+
inline bool deduplicate_xyz(mapbox::geojson::feature_collection &fc)
607+
{
608+
bool removed = false;
609+
for (auto &f : fc) {
610+
removed |= deduplicate_xyz(f);
611+
}
612+
return removed;
613+
}
614+
inline bool deduplicate_xyz(mapbox::geojson::geojson &geojson)
615+
{
616+
return geojson.match(
617+
[](mapbox::geojson::geometry &g) { return deduplicate_xyz(g); },
618+
[](mapbox::geojson::feature &f) { return deduplicate_xyz(f); },
619+
[](mapbox::geojson::feature_collection &fc) {
620+
return deduplicate_xyz(fc);
621+
},
622+
[](auto &) { return false; });
623+
}
624+
441625
} // namespace cubao
442626

443627
#endif

0 commit comments

Comments
 (0)