refactoring
This commit is contained in:
parent
2fb157ef37
commit
4733b0c676
26 changed files with 774 additions and 406 deletions
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
|
||||
#define UNUSED(expr) do { (void)(expr); } while (0)
|
||||
#define TIME() std::chrono::high_resolution_clock::now()
|
||||
|
|
@ -39,10 +40,18 @@ inline uint64_t atoul(const char* p) {
|
|||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline float atof(const char* p, uint8_t mn) {
|
||||
inline bool isFloatingPoint(const std::string& str) {
|
||||
std::stringstream ss(str);
|
||||
double f;
|
||||
ss >> std::noskipws >> f;
|
||||
return ss.eof() && ! ss.fail();
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline double atof(const char* p, uint8_t mn) {
|
||||
// this atof implementation works only on "normal" float strings like
|
||||
// 56.445 or -345.00, but should be faster than std::atof
|
||||
float ret = 0.0;
|
||||
double ret = 0.0;
|
||||
bool neg = false;
|
||||
if (*p == '-') {
|
||||
neg = true;
|
||||
|
|
@ -56,14 +65,14 @@ inline float atof(const char* p, uint8_t mn) {
|
|||
|
||||
if (*p == '.') {
|
||||
p++;
|
||||
float f = 0;
|
||||
double f = 0;
|
||||
uint8_t n = 0;
|
||||
|
||||
for (; n < mn && *p >= '0' && *p <= '9'; n++, p++) {
|
||||
f = f * 10.0 + (*p - '0');
|
||||
}
|
||||
|
||||
if (n < 11)
|
||||
if (n < 10)
|
||||
ret += f / pow10[n];
|
||||
else
|
||||
ret += f / std::pow(10, n);
|
||||
|
|
|
|||
|
|
@ -175,6 +175,18 @@ inline size_t prefixEditDist(const std::string& prefix, const std::string& s) {
|
|||
return prefixEditDist(prefix, s, s.size());
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline std::string toUpper(std::string str) {
|
||||
std::transform(str.begin(), str.end(),str.begin(), toupper);
|
||||
return str;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline std::string toLower(std::string str) {
|
||||
std::transform(str.begin(), str.end(),str.begin(), tolower);
|
||||
return str;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <class Iter>
|
||||
inline std::string implode(Iter begin, const Iter& end, const char* del) {
|
||||
|
|
@ -190,6 +202,25 @@ inline std::string implode(Iter begin, const Iter& end, const char* del) {
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline std::string normalizeWhiteSpace(const std::string& input) {
|
||||
std::string ret;
|
||||
bool ws = false;
|
||||
for (size_t i = 0; i < input.size(); i++) {
|
||||
if (std::isspace(input[i])) {
|
||||
if (!ws) {
|
||||
ret += " ";
|
||||
ws = true;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
ws = false;
|
||||
ret += input[i];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline std::string implode(const std::vector<T>& vec, const char* del) {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "util/Misc.h"
|
||||
#include "util/String.h"
|
||||
#include "util/geo/Box.h"
|
||||
#include "util/geo/Line.h"
|
||||
#include "util/geo/Point.h"
|
||||
|
|
@ -734,6 +735,45 @@ inline double dist(const Point<T>& p1, const Point<T>& p2) {
|
|||
return dist(p1.getX(), p1.getY(), p2.getX(), p2.getY());
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline Point<T> pointFromWKT(std::string wkt) {
|
||||
wkt = util::normalizeWhiteSpace(util::trim(wkt));
|
||||
if (wkt.rfind("POINT") == 0 || wkt.rfind("MPOINT") == 0) {
|
||||
size_t b = wkt.find("(") + 1;
|
||||
size_t e = wkt.find(")", b);
|
||||
if (b > e) throw std::runtime_error("Could not parse WKT");
|
||||
auto xy = util::split(util::trim(wkt.substr(b, e - b)), ' ');
|
||||
if (xy.size() < 2) throw std::runtime_error("Could not parse WKT");
|
||||
double x = atof(xy[0].c_str());
|
||||
double y = atof(xy[1].c_str());
|
||||
return Point<T>(x, y);
|
||||
}
|
||||
throw std::runtime_error("Could not parse WKT");
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline Line<T> lineFromWKT(std::string wkt) {
|
||||
wkt = util::normalizeWhiteSpace(util::trim(wkt));
|
||||
if (wkt.rfind("LINESTRING") == 0 || wkt.rfind("MLINESTRING") == 0) {
|
||||
Line<T> ret;
|
||||
size_t b = wkt.find("(") + 1;
|
||||
size_t e = wkt.find(")", b);
|
||||
if (b > e) throw std::runtime_error("Could not parse WKT");
|
||||
auto pairs = util::split(wkt.substr(b, e - b), ',');
|
||||
for (const auto& p : pairs) {
|
||||
auto xy = util::split(util::trim(p), ' ');
|
||||
if (xy.size() < 2) throw std::runtime_error("Could not parse WKT");
|
||||
double x = atof(xy[0].c_str());
|
||||
double y = atof(xy[1].c_str());
|
||||
ret.push_back({x, y});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
throw std::runtime_error("Could not parse WKT");
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline std::string getWKT(const Point<T>& p) {
|
||||
|
|
@ -1479,6 +1519,24 @@ inline double webMercMeterDist(const G1& a, const G2& b) {
|
|||
|
||||
return util::geo::dist(a, b) * cos((latA + latB) / 2.0);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline double webMercLen(const Line<T>& g) {
|
||||
double ret = 0;
|
||||
for (size_t i = 1; i < g.size(); i++) ret += webMercMeterDist(g[i - 1], g[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename G>
|
||||
inline double webMercDistFactor(const G& a) {
|
||||
// euclidean distance on web mercator is in meters on equator,
|
||||
// and proportional to cos(lat) in both y directions
|
||||
|
||||
double lat = 2 * atan(exp(a.getY() / 6378137.0)) - 1.5707965;
|
||||
return cos(lat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,6 @@
|
|||
#include "util/geo/output/GeoJsonOutput.h"
|
||||
#include "util/graph/Graph.h"
|
||||
|
||||
using util::toString;
|
||||
using util::graph::Graph;
|
||||
|
||||
namespace util {
|
||||
namespace geo {
|
||||
namespace output {
|
||||
|
|
@ -22,7 +19,7 @@ class GeoGraphJsonOutput {
|
|||
public:
|
||||
inline GeoGraphJsonOutput(){};
|
||||
template <typename N, typename E>
|
||||
void print(const Graph<N, E>& outG, std::ostream& str);
|
||||
void print(const util::graph::Graph<N, E>& outG, std::ostream& str);
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ void GeoGraphJsonOutput::print(const util::graph::Graph<N, E>& outG,
|
|||
for (util::graph::Node<N, E>* n : outG.getNds()) {
|
||||
if (!n->pl().getGeom()) continue;
|
||||
|
||||
json::Dict props{{"id", toString(n)},
|
||||
{"deg", toString(n->getDeg())},
|
||||
{"deg_out", toString(n->getOutDeg())},
|
||||
{"deg_in", toString(n->getInDeg())}};
|
||||
json::Dict props{{"id", util::toString(n)},
|
||||
{"deg", util::toString(n->getDeg())},
|
||||
{"deg_out", util::toString(n->getOutDeg())},
|
||||
{"deg_in", util::toString(n->getInDeg())}};
|
||||
|
||||
auto addProps = n->pl().getAttrs();
|
||||
props.insert(addProps.begin(), addProps.end());
|
||||
|
|
@ -38,9 +38,9 @@ void GeoGraphJsonOutput::print(const util::graph::Graph<N, E>& outG,
|
|||
for (graph::Edge<N, E>* e : n->getAdjListOut()) {
|
||||
// to avoid double output for undirected graphs
|
||||
if (e->getFrom() != n) continue;
|
||||
json::Dict props{{"from", toString(e->getFrom())},
|
||||
{"to", toString(e->getTo())},
|
||||
{"id", toString(e)}};
|
||||
json::Dict props{{"from", util::toString(e->getFrom())},
|
||||
{"to", util::toString(e->getTo())},
|
||||
{"id", util::toString(e)}};
|
||||
|
||||
auto addProps = e->pl().getAttrs();
|
||||
props.insert(addProps.begin(), addProps.end());
|
||||
|
|
|
|||
|
|
@ -17,9 +17,18 @@ GeoJsonOutput::GeoJsonOutput(std::ostream& str) : _wr(&str, 10, true) {
|
|||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
GeoJsonOutput::~GeoJsonOutput() {
|
||||
flush();
|
||||
GeoJsonOutput::GeoJsonOutput(std::ostream& str, json::Val attrs)
|
||||
: _wr(&str, 10, true) {
|
||||
_wr.obj();
|
||||
_wr.keyVal("type", "FeatureCollection");
|
||||
_wr.key("properties");
|
||||
_wr.val(attrs);
|
||||
_wr.key("features");
|
||||
_wr.arr();
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
GeoJsonOutput::~GeoJsonOutput() { flush(); }
|
||||
|
||||
// _____________________________________________________________________________
|
||||
void GeoJsonOutput::flush() { _wr.closeAll(); }
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ namespace output {
|
|||
class GeoJsonOutput {
|
||||
public:
|
||||
GeoJsonOutput(std::ostream& str);
|
||||
GeoJsonOutput(std::ostream& str, json::Val attrs);
|
||||
~GeoJsonOutput();
|
||||
template <typename T>
|
||||
void print(const Point<T>& p, json::Val attrs);
|
||||
|
|
|
|||
|
|
@ -1001,9 +1001,82 @@ CASE("nullable") {
|
|||
}
|
||||
}},
|
||||
|
||||
// ___________________________________________________________________________
|
||||
{
|
||||
CASE("geomwkt") {
|
||||
auto p = pointFromWKT<double>("POINT(10 50)");
|
||||
EXPECT(p.getX() == approx(10));
|
||||
EXPECT(p.getY() == approx(50));
|
||||
|
||||
p = pointFromWKT<double>("POINT( 10 50)");
|
||||
EXPECT(p.getX() == approx(10));
|
||||
EXPECT(p.getY() == approx(50));
|
||||
|
||||
p = pointFromWKT<double>("POINT (10 50 30)");
|
||||
EXPECT(p.getX() == approx(10));
|
||||
EXPECT(p.getY() == approx(50));
|
||||
|
||||
p = pointFromWKT<double>("POINT (10 50 30)");
|
||||
EXPECT(p.getX() == approx(10));
|
||||
EXPECT(p.getY() == approx(50));
|
||||
|
||||
p = pointFromWKT<double>("POINT(10 50 30)");
|
||||
EXPECT(p.getX() == approx(10));
|
||||
EXPECT(p.getY() == approx(50));
|
||||
|
||||
p = pointFromWKT<double>("POINT (10 50) ");
|
||||
EXPECT(p.getX() == approx(10));
|
||||
EXPECT(p.getY() == approx(50));
|
||||
|
||||
p = pointFromWKT<double>("MPOINT(10 50 30)");
|
||||
EXPECT(p.getX() == approx(10));
|
||||
EXPECT(p.getY() == approx(50));
|
||||
|
||||
p = pointFromWKT<double>("MPOINT(10 50)");
|
||||
EXPECT(p.getX() == approx(10));
|
||||
EXPECT(p.getY() == approx(50));
|
||||
|
||||
p = pointFromWKT<double>("POINT(10.05 50.05)");
|
||||
EXPECT(p.getX() == approx(10.05));
|
||||
EXPECT(p.getY() == approx(50.05));
|
||||
|
||||
auto wktl = lineFromWKT<double>("LINESTRING(0 0, 1 1,2 3, 0 1)");
|
||||
EXPECT(wktl.size() == (size_t)4);
|
||||
EXPECT(wktl[0].getX() == approx(0));
|
||||
EXPECT(wktl[0].getY() == approx(0));
|
||||
EXPECT(wktl[1].getX() == approx(1));
|
||||
EXPECT(wktl[1].getY() == approx(1));
|
||||
EXPECT(wktl[2].getX() == approx(2));
|
||||
EXPECT(wktl[2].getY() == approx(3));
|
||||
EXPECT(wktl[3].getX() == approx(0));
|
||||
EXPECT(wktl[3].getY() == approx(1));
|
||||
|
||||
wktl = lineFromWKT<double>("MLINESTRING(0 0, 1 1,2 3, 0 1)");
|
||||
EXPECT(wktl.size() == (size_t)4);
|
||||
EXPECT(wktl[0].getX() == approx(0));
|
||||
EXPECT(wktl[0].getY() == approx(0));
|
||||
EXPECT(wktl[1].getX() == approx(1));
|
||||
EXPECT(wktl[1].getY() == approx(1));
|
||||
EXPECT(wktl[2].getX() == approx(2));
|
||||
EXPECT(wktl[2].getY() == approx(3));
|
||||
EXPECT(wktl[3].getX() == approx(0));
|
||||
EXPECT(wktl[3].getY() == approx(1));
|
||||
|
||||
wktl = lineFromWKT<double>("MLINESTRING (0 0, 1 1,2 3, 0 1 )");
|
||||
EXPECT(wktl.size() == (size_t)4);
|
||||
EXPECT(wktl[0].getX() == approx(0));
|
||||
EXPECT(wktl[0].getY() == approx(0));
|
||||
EXPECT(wktl[1].getX() == approx(1));
|
||||
EXPECT(wktl[1].getY() == approx(1));
|
||||
EXPECT(wktl[2].getX() == approx(2));
|
||||
EXPECT(wktl[2].getY() == approx(3));
|
||||
EXPECT(wktl[3].getX() == approx(0));
|
||||
EXPECT(wktl[3].getY() == approx(1));
|
||||
}},
|
||||
// ___________________________________________________________________________
|
||||
{
|
||||
CASE("geometry") {
|
||||
|
||||
geo::Point<double> a(1, 2);
|
||||
geo::Point<double> b(2, 3);
|
||||
geo::Point<double> c(4, 5);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue