|
4 | 4 | #include <array> |
5 | 5 | #include <mapbox/geojson_impl.hpp> |
6 | 6 | #include <mapbox/geojson_value_impl.hpp> |
| 7 | +#include <set> |
7 | 8 |
|
8 | 9 | #include "rapidjson/error/en.h" |
9 | 10 | #include "rapidjson/filereadstream.h" |
@@ -212,25 +213,27 @@ std::string dump(const mapbox::geojson::geojson &geojson, // |
212 | 213 |
|
213 | 214 | std::string Encoder::encode(const mapbox::geojson::geojson &geojson) |
214 | 215 | { |
| 216 | + std::string data; |
| 217 | + Encoder::Pbf pbf{data}; |
| 218 | + |
215 | 219 | dim = MAPBOX_GEOBUF_DEFAULT_DIM; |
216 | 220 | e = 1; |
217 | 221 | keys.clear(); |
218 | 222 | analyze(geojson); |
219 | | - |
220 | | - std::vector<std::pair<const std::string *, uint32_t>> keys_vec; |
221 | | - keys_vec.reserve(keys.size()); |
222 | | - for (auto &pair : keys) { |
223 | | - keys_vec.emplace_back(&pair.first, pair.second); |
| 223 | + if (onlyXY) { |
| 224 | + dim = 2u; |
224 | 225 | } |
225 | | - std::sort(keys_vec.begin(), keys_vec.end(), |
226 | | - [](const auto &kv1, const auto &kv2) { |
227 | | - return kv1.second < kv2.second; |
228 | | - }); |
229 | 226 |
|
230 | | - std::string data; |
231 | | - Encoder::Pbf pbf{data}; |
232 | | - for (auto &kv : keys_vec) { |
233 | | - pbf.add_string(1, *kv.first); |
| 227 | + { |
| 228 | + auto kk = std::set<std::string>(); |
| 229 | + for (auto &pair : keys) { |
| 230 | + kk.insert(pair.first); |
| 231 | + } |
| 232 | + int idx = -1; |
| 233 | + for (auto &k : kk) { |
| 234 | + pbf.add_string(1, k); |
| 235 | + keys[k] = ++idx; |
| 236 | + } |
234 | 237 | } |
235 | 238 | if (dim != MAPBOX_GEOBUF_DEFAULT_DIM) { |
236 | 239 | pbf.add_uint32(2, dim); |
@@ -346,15 +349,23 @@ void Encoder::analyzePoints(const PointsType &points) |
346 | 349 | } |
347 | 350 | } |
348 | 351 |
|
| 352 | +inline double ROUND(double v, double s) |
| 353 | +{ |
| 354 | + return std::floor(v * s + 0.5) / s; |
| 355 | + // return std::round(v * s) / s; |
| 356 | +} |
| 357 | + |
349 | 358 | void Encoder::analyzePoint(const mapbox::geojson::point &point) |
350 | 359 | { |
351 | | - dim = std::max(point.z == 0 ? dimXY : dimXYZ, dim); |
| 360 | + if (!onlyXY) { |
| 361 | + dim = std::max(point.z == 0 ? dimXY : dimXYZ, dim); |
| 362 | + } |
352 | 363 | if (e >= maxPrecision) { |
353 | 364 | return; |
354 | 365 | } |
355 | 366 | const double *ptr = &point.x; |
356 | 367 | for (int i = 0; i < dim; ++i) { |
357 | | - while (std::round(ptr[i] * e) / e != ptr[i] && e < maxPrecision) { |
| 368 | + while (ROUND(ptr[i], e) != ptr[i] && e < maxPrecision) { |
358 | 369 | e *= 10; |
359 | 370 | } |
360 | 371 | } |
@@ -502,7 +513,7 @@ void Encoder::writePoint(const mapbox::geojson::point &point, Encoder::Pbf &pbf) |
502 | 513 | coords.reserve(dim); |
503 | 514 | const double *ptr = &point.x; |
504 | 515 | for (int i = 0; i < dim; ++i) { |
505 | | - coords.push_back(static_cast<int64_t>(std::round(ptr[i] * e))); |
| 516 | + coords.push_back(static_cast<int64_t>(std::floor(ptr[i] * e + 0.5))); |
506 | 517 | } |
507 | 518 | pbf.add_packed_sint64(3, coords.begin(), coords.end()); |
508 | 519 | } |
@@ -570,7 +581,8 @@ void Encoder::populateLine(std::vector<int64_t> &coords, // |
570 | 581 | for (int i = 0; i < len; ++i) { |
571 | 582 | const double *ptr = &line[i].x; |
572 | 583 | for (int j = 0; j < dim; ++j) { |
573 | | - auto n = static_cast<int64_t>(std::round(ptr[j] * e)) - sum[j]; |
| 584 | + auto n = |
| 585 | + static_cast<int64_t>(std::floor(ptr[j] * e + 0.5)) - sum[j]; |
574 | 586 | coords.push_back(n); |
575 | 587 | sum[j] += n; |
576 | 588 | } |
|
0 commit comments