update util
This commit is contained in:
parent
a8c23b2c02
commit
580f1807f3
29 changed files with 2762 additions and 81 deletions
|
@ -410,7 +410,8 @@ void RouterImpl<TW>::hops(const EdgeCandGroup& froms, const EdgeCandGroup& tos,
|
|||
|
||||
if (c < maxCost) {
|
||||
rCosts->push_back({{frId, toId}, c});
|
||||
if (TW::NEED_DIST) dists->push_back({{frId, toId}, dist});
|
||||
if (TW::NEED_DIST)
|
||||
dists->push_back({{frId, toId}, static_cast<uint32_t>(dist)});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
1700
src/util/3rdparty/RTree.h
vendored
Normal file
1700
src/util/3rdparty/RTree.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
263
src/util/Misc.h
263
src/util/Misc.h
|
@ -19,6 +19,7 @@
|
|||
#include <map>
|
||||
#include <thread>
|
||||
#include "3rdparty/dtoa_milo.h"
|
||||
#include "util/String.h"
|
||||
|
||||
#define UNUSED(expr) do { (void)(expr); } while (0)
|
||||
#define TIME() std::chrono::high_resolution_clock::now()
|
||||
|
@ -55,6 +56,156 @@
|
|||
|
||||
namespace util {
|
||||
|
||||
const static std::map<std::string, std::string> HTML_COLOR_NAMES = {
|
||||
{"aliceblue","F0F8FF"},
|
||||
{"antiquewhite","FAEBD7"},
|
||||
{"aqua","00FFFF"},
|
||||
{"aquamarine","7FFFD4"},
|
||||
{"azure","F0FFFF"},
|
||||
{"beige","F5F5DC"},
|
||||
{"bisque","FFE4C4"},
|
||||
{"black","000000"},
|
||||
{"blanchedalmond","FFEBCD"},
|
||||
{"blue","0000FF"},
|
||||
{"blueviolet","8A2BE2"},
|
||||
{"brown","A52A2A"},
|
||||
{"burlywood","DEB887"},
|
||||
{"cadetblue","5F9EA0"},
|
||||
{"chartreuse","7FFF00"},
|
||||
{"chocolate","D2691E"},
|
||||
{"coral","FF7F50"},
|
||||
{"cornflowerblue","6495ED"},
|
||||
{"cornsilk","FFF8DC"},
|
||||
{"crimson","DC143C"},
|
||||
{"cyan","00FFFF"},
|
||||
{"darkblue","00008B"},
|
||||
{"darkcyan","008B8B"},
|
||||
{"darkgoldenrod","B8860B"},
|
||||
{"darkgray","A9A9A9"},
|
||||
{"darkgreen","006400"},
|
||||
{"darkgrey","A9A9A9"},
|
||||
{"darkkhaki","BDB76B"},
|
||||
{"darkmagenta","8B008B"},
|
||||
{"darkolivegreen","556B2F"},
|
||||
{"darkorange","FF8C00"},
|
||||
{"darkorchid","9932CC"},
|
||||
{"darkred","8B0000"},
|
||||
{"darksalmon","E9967A"},
|
||||
{"darkseagreen","8FBC8F"},
|
||||
{"darkslateblue","483D8B"},
|
||||
{"darkslategray","2F4F4F"},
|
||||
{"darkslategrey","2F4F4F"},
|
||||
{"darkturquoise","00CED1"},
|
||||
{"darkviolet","9400D3"},
|
||||
{"deeppink","FF1493"},
|
||||
{"deepskyblue","00BFFF"},
|
||||
{"dimgray","696969"},
|
||||
{"dimgrey","696969"},
|
||||
{"dodgerblue","1E90FF"},
|
||||
{"firebrick","B22222"},
|
||||
{"floralwhite","FFFAF0"},
|
||||
{"forestgreen","228B22"},
|
||||
{"fuchsia","FF00FF"},
|
||||
{"gainsboro","DCDCDC"},
|
||||
{"ghostwhite","F8F8FF"},
|
||||
{"gold","FFD700"},
|
||||
{"goldenrod","DAA520"},
|
||||
{"gray","808080"},
|
||||
{"green","008000"},
|
||||
{"greenyellow","ADFF2F"},
|
||||
{"grey","808080"},
|
||||
{"honeydew","F0FFF0"},
|
||||
{"hotpink","FF69B4"},
|
||||
{"indianred","CD5C5C"},
|
||||
{"indigo","4B0082"},
|
||||
{"ivory","FFFFF0"},
|
||||
{"khaki","F0E68C"},
|
||||
{"lavender","E6E6FA"},
|
||||
{"lavenderblush","FFF0F5"},
|
||||
{"lawngreen","7CFC00"},
|
||||
{"lemonchiffon","FFFACD"},
|
||||
{"lightblue","ADD8E6"},
|
||||
{"lightcoral","F08080"},
|
||||
{"lightcyan","E0FFFF"},
|
||||
{"lightgoldenrodyellow","FAFAD2"},
|
||||
{"lightgray","D3D3D3"},
|
||||
{"lightgreen","90EE90"},
|
||||
{"lightgrey","D3D3D3"},
|
||||
{"lightpink","FFB6C1"},
|
||||
{"lightsalmon","FFA07A"},
|
||||
{"lightseagreen","20B2AA"},
|
||||
{"lightskyblue","87CEFA"},
|
||||
{"lightslategray","778899"},
|
||||
{"lightslategrey","778899"},
|
||||
{"lightsteelblue","B0C4DE"},
|
||||
{"lightyellow","FFFFE0"},
|
||||
{"lime","00FF00"},
|
||||
{"limegreen","32CD32"},
|
||||
{"linen","FAF0E6"},
|
||||
{"magenta","FF00FF"},
|
||||
{"maroon","800000"},
|
||||
{"mediumaquamarine","66CDAA"},
|
||||
{"mediumblue","0000CD"},
|
||||
{"mediumorchid","BA55D3"},
|
||||
{"mediumpurple","9370DB"},
|
||||
{"mediumseagreen","3CB371"},
|
||||
{"mediumslateblue","7B68EE"},
|
||||
{"mediumspringgreen","00FA9A"},
|
||||
{"mediumturquoise","48D1CC"},
|
||||
{"mediumvioletred","C71585"},
|
||||
{"midnightblue","191970"},
|
||||
{"mintcream","F5FFFA"},
|
||||
{"mistyrose","FFE4E1"},
|
||||
{"moccasin","FFE4B5"},
|
||||
{"navajowhite","FFDEAD"},
|
||||
{"navy","000080"},
|
||||
{"oldlace","FDF5E6"},
|
||||
{"olive","808000"},
|
||||
{"olivedrab","6B8E23"},
|
||||
{"orange","FFA500"},
|
||||
{"orangered","FF4500"},
|
||||
{"orchid","DA70D6"},
|
||||
{"palegoldenrod","EEE8AA"},
|
||||
{"palegreen","98FB98"},
|
||||
{"paleturquoise","AFEEEE"},
|
||||
{"palevioletred","DB7093"},
|
||||
{"papayawhip","FFEFD5"},
|
||||
{"peachpuff","FFDAB9"},
|
||||
{"peru","CD853F"},
|
||||
{"pink","FFC0CB"},
|
||||
{"plum","DDA0DD"},
|
||||
{"powderblue","B0E0E6"},
|
||||
{"purple","800080"},
|
||||
{"red","FF0000"},
|
||||
{"rosybrown","BC8F8F"},
|
||||
{"royalblue","4169E1"},
|
||||
{"saddlebrown","8B4513"},
|
||||
{"salmon","FA8072"},
|
||||
{"sandybrown","F4A460"},
|
||||
{"seagreen","2E8B57"},
|
||||
{"seashell","FFF5EE"},
|
||||
{"sienna","A0522D"},
|
||||
{"silver","C0C0C0"},
|
||||
{"skyblue","87CEEB"},
|
||||
{"slateblue","6A5ACD"},
|
||||
{"slategray","708090"},
|
||||
{"slategrey","708090"},
|
||||
{"snow","FFFAFA"},
|
||||
{"springgreen","00FF7F"},
|
||||
{"steelblue","4682B4"},
|
||||
{"tan","D2B48C"},
|
||||
{"teal","008080"},
|
||||
{"thistle","D8BFD8"},
|
||||
{"tomato","FF6347"},
|
||||
{"turquoise","40E0D0"},
|
||||
{"violet","EE82EE"},
|
||||
{"wheat","F5DEB3"},
|
||||
{"white","FFFFFF"},
|
||||
{"whitesmoke","F5F5F5"},
|
||||
{"yellow","FFFF00"},
|
||||
{"yellowgreen","9ACD32"}
|
||||
};
|
||||
|
||||
struct hashPair {
|
||||
template <class T1, class T2>
|
||||
size_t operator()(const std::pair<T1, T2>& p) const {
|
||||
|
@ -270,24 +421,6 @@ inline std::string getHomeDir() {
|
|||
return ret;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline char* readableSize(double size, size_t n, char* buf) {
|
||||
int i = 0;
|
||||
const char* units[] = {"B", "kB", "MB", "GB", "TB", "PB"};
|
||||
while (size > 1024 && i < 5) {
|
||||
size /= 1024;
|
||||
i++;
|
||||
}
|
||||
snprintf(buf, n, "%.*f %s", i, size, units[i]);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline std::string readableSize(double size) {
|
||||
char buffer[30];
|
||||
return readableSize(size, 30, buffer);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline std::string getTmpDir() {
|
||||
// first, check if an env variable is set
|
||||
|
@ -330,6 +463,100 @@ inline std::string getTmpFName(std::string dir, std::string name,
|
|||
return f;
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
inline std::string rgbToHex(int r, int g, int b) {
|
||||
char hexcol[16];
|
||||
snprintf(hexcol, sizeof hexcol, "%02x%02x%02x", r, g, b);
|
||||
return hexcol;
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
inline void hsvToRgb(float* r, float* g, float* b, float h, float s, float v) {
|
||||
int i;
|
||||
float f, p, q, t;
|
||||
|
||||
if (s == 0) {
|
||||
*r = *g = *b = v;
|
||||
return;
|
||||
}
|
||||
|
||||
h /= 60;
|
||||
i = floor(h);
|
||||
f = h - i;
|
||||
p = v * (1 - s);
|
||||
q = v * (1 - s * f);
|
||||
t = v * (1 - s * (1 - f));
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
*r = v;
|
||||
*g = t;
|
||||
*b = p;
|
||||
break;
|
||||
case 1:
|
||||
*r = q;
|
||||
*g = v;
|
||||
*b = p;
|
||||
break;
|
||||
case 2:
|
||||
*r = p;
|
||||
*g = v;
|
||||
*b = t;
|
||||
break;
|
||||
case 3:
|
||||
*r = p;
|
||||
*g = q;
|
||||
*b = v;
|
||||
break;
|
||||
case 4:
|
||||
*r = t;
|
||||
*g = p;
|
||||
*b = v;
|
||||
break;
|
||||
default:
|
||||
*r = v;
|
||||
*g = p;
|
||||
*b = q;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
inline std::string normHtmlColor(const std::string& col) {
|
||||
auto i = HTML_COLOR_NAMES.find(toLower(col));
|
||||
if (i != HTML_COLOR_NAMES.end()) return i->second;
|
||||
return col;
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
inline std::string randomHtmlColor() {
|
||||
double goldenRatio = 0.618033988749895;
|
||||
double h = static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
|
||||
h += goldenRatio;
|
||||
h = fmod(h, 1.0);
|
||||
float r, g, b;
|
||||
hsvToRgb(&r, &g, &b, h * 360, 0.95, 0.95);
|
||||
return rgbToHex(r * 256, g * 256, b * 256);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline char* readableSize(double size, size_t n, char* buf) {
|
||||
int i = 0;
|
||||
const char* units[] = {"B", "kB", "MB", "GB", "TB", "PB"};
|
||||
while (size > 1024 && i < 5) {
|
||||
size /= 1024;
|
||||
i++;
|
||||
}
|
||||
snprintf(buf, n, "%.*f %s", i, size, units[i]);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline std::string readableSize(double size) {
|
||||
char buffer[30];
|
||||
return readableSize(size, 30, buffer);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
class approx {
|
||||
public:
|
||||
|
|
|
@ -22,6 +22,12 @@
|
|||
|
||||
namespace util {
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline bool endsWith(const std::string& a, const std::string& suff) {
|
||||
if (suff.size() > a.size()) return false;
|
||||
return a.compare(a.length() - suff.length(), suff.length(), suff) == 0;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline std::string urlDecode(const std::string& encoded) {
|
||||
std::string decoded;
|
||||
|
@ -139,19 +145,30 @@ inline std::vector<std::string> split(std::string in, char sep) {
|
|||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline std::string ltrim(std::string str) {
|
||||
str.erase(0, str.find_first_not_of(" \t\n\v\f\r"));
|
||||
inline std::string ltrim(std::string str, std::string c) {
|
||||
str.erase(0, str.find_first_not_of(c));
|
||||
return str;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline std::string rtrim(std::string str) {
|
||||
str.erase(str.find_last_not_of(" \t\n\v\f\r") + 1);
|
||||
inline std::string rtrim(std::string str, std::string c) {
|
||||
str.erase(str.find_last_not_of(c) + 1);
|
||||
return str;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline std::string trim(std::string str) { return ltrim(rtrim(str)); }
|
||||
inline std::string trim(std::string str, std::string c) {
|
||||
return ltrim(rtrim(str, c), c);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline std::string ltrim(std::string str) { return ltrim(str, " \t\n\v\f\r"); }
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline std::string rtrim(std::string str) { return rtrim(str, " \t\n\v\f\r"); }
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline std::string trim(std::string str) { return trim(str, " \t\n\v\f\r"); }
|
||||
|
||||
// _____________________________________________________________________________
|
||||
inline size_t editDist(const std::string& s1, const std::string& s2) {
|
||||
|
|
|
@ -707,6 +707,55 @@ inline Point<T> intersection(const LineSegment<T>& s1,
|
|||
return intersection(s1.first, s1.second, s2.first, s2.second);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline std::vector<Point<T>> intersection(const Line<T>& l1,
|
||||
const Line<T>& l2) {
|
||||
|
||||
std::vector<Point<T>> ret;
|
||||
|
||||
// TODO: better implementation than this naive baseline
|
||||
for (size_t i = 1; i < l1.size(); i++) {
|
||||
for (size_t j = 1; j < l2.size(); j++) {
|
||||
LineSegment<T> a = {l1[i-1], l1[i]};
|
||||
LineSegment<T> b = {l2[j-1], l2[j]};
|
||||
if (intersects(a, b)) ret.push_back(intersection(a, b));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline Box<T> intersection(const Box<T>& b1, const Box<T>& b2) {
|
||||
if (!intersects(b1, b2)) return Box<T>();
|
||||
|
||||
T llx, lly, urx, ury;
|
||||
|
||||
if (b1.getLowerLeft().getX() > b2.getLowerLeft().getX())
|
||||
llx = b1.getLowerLeft().getX();
|
||||
else
|
||||
llx = b2.getLowerLeft().getX();
|
||||
|
||||
if (b1.getLowerLeft().getY() > b2.getLowerLeft().getY())
|
||||
lly = b1.getLowerLeft().getY();
|
||||
else
|
||||
lly = b2.getLowerLeft().getY();
|
||||
|
||||
if (b1.getUpperRight().getX() < b2.getUpperRight().getX())
|
||||
urx = b1.getUpperRight().getX();
|
||||
else
|
||||
urx = b2.getUpperRight().getX();
|
||||
|
||||
if (b1.getUpperRight().getY() < b2.getUpperRight().getY())
|
||||
ury = b1.getUpperRight().getY();
|
||||
else
|
||||
ury = b2.getUpperRight().getY();
|
||||
|
||||
return Box<T>{{llx, lly}, {urx, ury}};
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline bool lineIntersects(T p1x, T p1y, T q1x, T q1y, T p2x, T p2y, T q2x,
|
||||
|
@ -898,6 +947,27 @@ inline double crossProd(const Point<T>& p, const LineSegment<T>& ls) {
|
|||
Point<T>(p.getX() - ls.first.getX(), p.getY() - ls.first.getY()));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline double dist(const Polygon<T>& poly1, const Polygon<T>& poly2) {
|
||||
if (contains(poly1, poly2) || contains(poly2, poly1)) return 0;
|
||||
return dist(poly1.getOuter(), poly2.getOuter());
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline double dist(const Line<T>& l, const Polygon<T>& poly) {
|
||||
if (contains(l, poly)) return 0;
|
||||
return dist(l, poly.getOuter());
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline double dist(const Point<T>& p, const Polygon<T>& poly) {
|
||||
if (contains(p, poly)) return 0;
|
||||
return dist(p, poly.getOuter());
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline double dist(const Point<T>& p1, const Point<T>& p2) {
|
||||
|
@ -908,6 +978,7 @@ inline double dist(const Point<T>& p1, const Point<T>& p2) {
|
|||
template <typename T>
|
||||
inline Point<T> pointFromWKT(std::string wkt) {
|
||||
wkt = util::normalizeWhiteSpace(util::trim(wkt));
|
||||
for (size_t i = 0; i < 6;i++) wkt[i] = toupper(wkt[i]);
|
||||
if (wkt.rfind("POINT") == 0 || wkt.rfind("MPOINT") == 0) {
|
||||
size_t b = wkt.find("(") + 1;
|
||||
size_t e = wkt.find(")", b);
|
||||
|
@ -925,6 +996,7 @@ inline Point<T> pointFromWKT(std::string wkt) {
|
|||
template <typename T>
|
||||
inline Line<T> lineFromWKT(std::string wkt) {
|
||||
wkt = util::normalizeWhiteSpace(util::trim(wkt));
|
||||
for (size_t i = 0; i < 11;i++) wkt[i] = toupper(wkt[i]);
|
||||
if (wkt.rfind("LINESTRING") == 0 || wkt.rfind("MLINESTRING") == 0) {
|
||||
Line<T> ret;
|
||||
size_t b = wkt.find("(") + 1;
|
||||
|
@ -943,6 +1015,96 @@ inline Line<T> lineFromWKT(std::string wkt) {
|
|||
throw std::runtime_error("Could not parse WKT");
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline MultiPolygon<T> multiPolygonFromWKT(std::string wkt) {
|
||||
wkt = util::normalizeWhiteSpace(util::trim(wkt));
|
||||
for (size_t i = 0; i < 13;i++) wkt[i] = toupper(wkt[i]);
|
||||
util::replaceAll(wkt, "))", ")!");
|
||||
util::replaceAll(wkt, ") )", ")!");
|
||||
if (wkt.rfind("MULTIPOLYGON") == 0 || wkt.rfind("MMULTIPOLYGON") == 0) {
|
||||
MultiPolygon<T> ret;
|
||||
size_t b = wkt.find("(") + 1;
|
||||
size_t e = wkt.rfind(")");
|
||||
if (b > e) throw std::runtime_error("Could not parse WKT");
|
||||
|
||||
auto polyPairs = util::split(wkt.substr(b, e - b), '!');
|
||||
|
||||
for (const auto& polyPair : polyPairs) {
|
||||
size_t b = polyPair.find("(") + 1;
|
||||
size_t e = polyPair.rfind(")");
|
||||
auto pairs = util::split(polyPair.substr(b, e - b), ')');
|
||||
|
||||
ret.push_back({});
|
||||
|
||||
for (size_t i = 0; i < pairs.size(); i++) {
|
||||
size_t b = pairs[i].find("(") + 1;
|
||||
size_t e = pairs[i].rfind(")", b);
|
||||
auto pairsLoc = util::split(pairs[i].substr(b, e - b), ',');
|
||||
|
||||
if (i > 0) {
|
||||
ret.back().getInners().push_back({});
|
||||
}
|
||||
|
||||
for (const auto& p : pairsLoc) {
|
||||
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());
|
||||
|
||||
if (i == 0) {
|
||||
ret.back().getOuter().push_back({x, y});
|
||||
} else {
|
||||
ret.back().getInners().back().push_back({x, y});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
throw std::runtime_error("Could not parse WKT");
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline Polygon<T> polygonFromWKT(std::string wkt) {
|
||||
wkt = util::normalizeWhiteSpace(util::trim(wkt));
|
||||
for (size_t i = 0; i < 8;i++) wkt[i] = toupper(wkt[i]);
|
||||
if (wkt.rfind("POLYGON") == 0 || wkt.rfind("MPOLYGON") == 0) {
|
||||
Polygon<T> ret;
|
||||
size_t b = wkt.find("(") + 1;
|
||||
size_t e = wkt.rfind(")");
|
||||
if (b > e) throw std::runtime_error("Could not parse WKT");
|
||||
|
||||
auto pairs = util::split(wkt.substr(b, e - b), ')');
|
||||
|
||||
for (size_t i = 0; i < pairs.size(); i++) {
|
||||
size_t b = pairs[i].find("(") + 1;
|
||||
size_t e = pairs[i].rfind(")", b);
|
||||
auto pairsLoc = util::split(pairs[i].substr(b, e - b), ',');
|
||||
|
||||
if (i > 0) {
|
||||
ret.getInners().push_back({});
|
||||
}
|
||||
|
||||
for (const auto& p : pairsLoc) {
|
||||
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());
|
||||
|
||||
if (i == 0) {
|
||||
ret.getOuter().push_back({x, y});
|
||||
} else {
|
||||
ret.getInners().back().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) {
|
||||
|
@ -1075,6 +1237,43 @@ inline double len(const Line<T>& g) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline bool shorterThan(const Line<T>& g, double d) {
|
||||
double ret = 0;
|
||||
for (size_t i = 1; i < g.size(); i++) {
|
||||
ret += dist(g[i - 1], g[i]);
|
||||
if (ret >= d) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline bool longerThan(const Line<T>& g, double d) {
|
||||
double ret = 0;
|
||||
for (size_t i = 1; i < g.size(); i++) {
|
||||
ret += dist(g[i - 1], g[i]);
|
||||
if (ret > d) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline bool longerThan(const Line<T>& a, const Line<T>& b, double d) {
|
||||
double ret = 0;
|
||||
for (size_t i = 1; i < a.size(); i++) {
|
||||
ret += dist(a[i - 1], a[i]);
|
||||
if (ret > d) return true;
|
||||
}
|
||||
for (size_t i = 1; i < b.size(); i++) {
|
||||
ret += dist(b[i - 1], b[i]);
|
||||
if (ret > d) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline Point<T> simplify(const Point<T>& g, double d) {
|
||||
|
@ -1317,6 +1516,9 @@ inline Polygon<T> buffer(const Polygon<T>& pol, double d, size_t points) {
|
|||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
inline Box<T> extendBox(const Box<T>& a, Box<T> b) {
|
||||
if (a.getLowerLeft().getX() > a.getUpperRight().getX()) return b;
|
||||
if (a.getLowerLeft().getY() > a.getUpperRight().getY()) return b;
|
||||
|
||||
b = extendBox(a.getLowerLeft(), b);
|
||||
b = extendBox(a.getUpperRight(), b);
|
||||
return b;
|
||||
|
@ -1458,10 +1660,14 @@ inline Polygon<T> convexHull(const RotatedBox<T>& b) {
|
|||
template <typename T>
|
||||
inline size_t convexHullImpl(const MultiPoint<T>& a, size_t p1, size_t p2,
|
||||
Line<T>* h) {
|
||||
// emergency stop
|
||||
if (h->size() >= a.size() + 1) return 0;
|
||||
|
||||
// quickhull by Barber, Dobkin & Huhdanpaa
|
||||
Point<T> pa;
|
||||
bool found = false;
|
||||
double maxDist = 0;
|
||||
|
||||
for (const auto& p : a) {
|
||||
double tmpDist = distToSegment((*h)[p1], (*h)[p2], p);
|
||||
double cp = crossProd(p, LineSegment<T>((*h)[p1], (*h)[p2]));
|
||||
|
@ -1485,11 +1691,11 @@ inline Polygon<T> convexHull(const MultiPoint<T>& l) {
|
|||
if (l.size() == 2) return convexHull(LineSegment<T>(l[0], l[1]));
|
||||
if (l.size() == 1) return convexHull(l[0]);
|
||||
|
||||
Point<T> left(std::numeric_limits<T>::max(), 0);
|
||||
Point<T> right(std::numeric_limits<T>::lowest(), 0);
|
||||
Point<T> left(std::numeric_limits<T>::max(), std::numeric_limits<T>::max());
|
||||
Point<T> right(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::lowest());
|
||||
for (const auto& p : l) {
|
||||
if (p.getX() < left.getX()) left = p;
|
||||
if (p.getX() > right.getX()) right = p;
|
||||
if (p.getX() < left.getX() || (p.getX() == left.getX() && p.getY() < left.getY())) left = p;
|
||||
if (p.getX() > right.getX() || (p.getX() == right.getX() && p.getY() > right.getY())) right = p;
|
||||
}
|
||||
|
||||
Line<T> hull{left, right};
|
||||
|
|
|
@ -82,10 +82,18 @@ class Grid {
|
|||
void add(size_t x, size_t y, V val);
|
||||
|
||||
void get(const Box<T>& btbox, std::set<V>* s) const;
|
||||
void get(const G<T>& geom, double d, std::set<V>* s) const;
|
||||
|
||||
template <template <typename> class GG>
|
||||
void get(const GG<T>& geom, double d, std::set<V>* s) const;
|
||||
|
||||
template <template <typename> class GG>
|
||||
void get(const std::vector<GG<T>>& geom, double d, std::set<V>* s) const;
|
||||
|
||||
void get(size_t x, size_t y, std::set<V>* s) const;
|
||||
void remove(V val);
|
||||
|
||||
const std::set<V>& getCell(size_t x, size_t y) const;
|
||||
|
||||
void getNeighbors(const V& val, double d, std::set<V>* s) const;
|
||||
void getCellNeighbors(const V& val, size_t d, std::set<V>* s) const;
|
||||
void getCellNeighbors(size_t x, size_t y, size_t xPerm, size_t yPerm,
|
||||
|
@ -99,6 +107,9 @@ class Grid {
|
|||
size_t getCellXFromX(double lon) const;
|
||||
size_t getCellYFromY(double lat) const;
|
||||
|
||||
Box<T> getBox(size_t x, size_t y) const;
|
||||
Box<T> getBBox() const { return _bb; };
|
||||
|
||||
private:
|
||||
double _width;
|
||||
double _height;
|
||||
|
@ -117,8 +128,6 @@ class Grid {
|
|||
std::set<V>** _grid;
|
||||
std::map<V, std::set<std::pair<size_t, size_t> > > _index;
|
||||
std::set<V> _removed;
|
||||
|
||||
Box<T> getBox(size_t x, size_t y) const;
|
||||
};
|
||||
|
||||
#include "util/geo/Grid.tpp"
|
||||
|
|
|
@ -95,7 +95,20 @@ void Grid<V, G, T>::get(const Box<T>& box, std::set<V>* s) const {
|
|||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
void Grid<V, G, T>::get(const G<T>& geom, double d, std::set<V>* s) const {
|
||||
template <template <typename> class GG>
|
||||
void Grid<V, G, T>::get(const GG<T>& geom, double d, std::set<V>* s) const {
|
||||
Box<T> a = getBoundingBox(geom);
|
||||
Box<T> b(
|
||||
Point<T>(a.getLowerLeft().getX() - d, a.getLowerLeft().getY() - d),
|
||||
Point<T>(a.getUpperRight().getX() + d, a.getUpperRight().getY() + d));
|
||||
return get(b, s);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
template <template <typename> class GG>
|
||||
void Grid<V, G, T>::get(const std::vector<GG<T>>& geom, double d,
|
||||
std::set<V>* s) const {
|
||||
Box<T> a = getBoundingBox(geom);
|
||||
Box<T> b(
|
||||
Point<T>(a.getLowerLeft().getX() - d, a.getLowerLeft().getY() - d),
|
||||
|
@ -117,6 +130,12 @@ void Grid<V, G, T>::get(size_t x, size_t y, std::set<V>* s) const {
|
|||
}
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
const std::set<V>& Grid<V, G, T>::getCell(size_t x, size_t y) const {
|
||||
return _grid[x][y];
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
void Grid<V, G, T>::remove(V val) {
|
||||
|
@ -182,7 +201,7 @@ void Grid<V, G, T>::getCellNeighbors(size_t cx, size_t cy, size_t xPerm,
|
|||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
std::set<std::pair<size_t, size_t> > Grid<V, G, T>::getCells(
|
||||
std::set<std::pair<size_t, size_t>> Grid<V, G, T>::getCells(
|
||||
const V& val) const {
|
||||
if (!_hasValIdx) throw GridException("No value index build!");
|
||||
return _index.find(val)->second;
|
||||
|
|
|
@ -29,14 +29,22 @@ class Point {
|
|||
return Point<T>(_x - p.getX(), _y - p.getY());
|
||||
}
|
||||
|
||||
// bool operator==(const Point<T>& p) const {
|
||||
// return p.getX() == _x && p.getY() == _y;
|
||||
// }
|
||||
|
||||
bool operator==(const Point<T>& p) const {
|
||||
return p.getX() == _x && p.getY() == _y;
|
||||
return fabs(p.getX() - _x) < 0.00001 && fabs(p.getY() - _y) < 0.00001;
|
||||
}
|
||||
|
||||
bool operator!=(const Point<T>& p) const {
|
||||
return !(*this == p);
|
||||
}
|
||||
|
||||
bool operator<(const Point<T>& p) const {
|
||||
return _x < p.getX() || (_x == p.getX() && _y < p.getY());
|
||||
}
|
||||
|
||||
private:
|
||||
T _x, _y;
|
||||
};
|
||||
|
|
|
@ -55,6 +55,18 @@ class PolyLine {
|
|||
PolyLine();
|
||||
PolyLine(const Point<T>& from, const Point<T>& to);
|
||||
PolyLine(const Line<T>& l);
|
||||
PolyLine(const PolyLine<T>& l);
|
||||
PolyLine(PolyLine<T>&& l);
|
||||
|
||||
PolyLine& operator=(PolyLine<T>&& other) {
|
||||
_line = std::move(other._line);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PolyLine& operator=(const PolyLine<T>& other) {
|
||||
_line = other._line;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PolyLine& operator<<(const Point<T>& p);
|
||||
PolyLine& operator>>(const Point<T>& p);
|
||||
|
@ -67,11 +79,14 @@ class PolyLine {
|
|||
PolyLine offsetted(double units) const;
|
||||
|
||||
const Line<T>& getLine() const;
|
||||
Line<T>& getLine();
|
||||
|
||||
double distTo(const PolyLine<T>& g) const;
|
||||
double distTo(const Point<T>& p) const;
|
||||
|
||||
double getLength() const;
|
||||
bool shorterThan(double d) const;
|
||||
bool longerThan(double d) const;
|
||||
|
||||
// return point at dist
|
||||
LinePoint<T> getPointAtDist(double dist) const;
|
||||
|
@ -117,6 +132,7 @@ class PolyLine {
|
|||
std::string getWKT() const;
|
||||
|
||||
PolyLine getOrthoLineAtDist(double d, double lengt) const;
|
||||
PolyLine getOrthoLineAt(double d, double lengt) const;
|
||||
|
||||
Point<T> interpolate(const Point<T>& a, const Point<T>& b, double p) const;
|
||||
|
||||
|
|
|
@ -12,6 +12,16 @@ PolyLine<T>::PolyLine(const Point<T>& from, const Point<T>& to) {
|
|||
*this << from << to;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
PolyLine<T>::PolyLine(const PolyLine<T>& l) : _line(l._line) {
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
PolyLine<T>::PolyLine(PolyLine<T>&& l) : _line(std::move(l._line)) {
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
PolyLine<T>::PolyLine(const Line<T>& l) : _line(l) {}
|
||||
|
@ -50,6 +60,12 @@ const Line<T>& PolyLine<T>::getLine() const {
|
|||
return _line;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
Line<T>& PolyLine<T>::getLine() {
|
||||
return _line;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
PolyLine<T> PolyLine<T>::offsetted(double units) const {
|
||||
|
@ -73,9 +89,10 @@ void PolyLine<T>::offsetPerp(double units) {
|
|||
if (_line.size() < 2) return;
|
||||
|
||||
Line<T> ret;
|
||||
ret.reserve(_line.size());
|
||||
Point<T> lastP = _line.front();
|
||||
|
||||
Point<T> *lastIns = 0, *befLastIns = 0;
|
||||
Point<T>*lastIns = 0, *befLastIns = 0;
|
||||
|
||||
for (size_t i = 1; i < _line.size(); i++) {
|
||||
Point<T> curP = _line[i];
|
||||
|
@ -99,22 +116,28 @@ void PolyLine<T>::offsetPerp(double units) {
|
|||
|
||||
if (lastIns && befLastIns &&
|
||||
lineIntersects(*lastIns, *befLastIns, lastP, curP)) {
|
||||
*lastIns = intersection(*lastIns, *befLastIns, lastP, curP);
|
||||
auto iSect = intersection(*lastIns, *befLastIns, lastP, curP);
|
||||
|
||||
double d = dist(lastP, *lastIns);
|
||||
double d2 = distToSegment(*lastIns, *befLastIns, lastP);
|
||||
double d = fmax(dist(lastP, iSect), dist(*lastIns, iSect));
|
||||
double d2 = distToSegment(iSect, *befLastIns, lastP);
|
||||
|
||||
if (d > fabs(units) * 2 && d2 < d - (fabs(units))) {
|
||||
PolyLine pl(*lastIns, *befLastIns);
|
||||
PolyLine pll(*lastIns, curP);
|
||||
if (d > fabs(units) * 2.0 && d2 < d - (fabs(units))) {
|
||||
PolyLine pl(iSect, *befLastIns);
|
||||
PolyLine pll(iSect, curP);
|
||||
pl = pl.getSegment(0, (d - (fabs(units))) / pl.getLength());
|
||||
pll = pll.getSegment(0, (d - (fabs(units))) / pll.getLength());
|
||||
|
||||
ret.push_back(pll.back());
|
||||
// careful, after push_back() below, lastIns might point to another
|
||||
// point because of reallocation
|
||||
*lastIns = pl.back();
|
||||
|
||||
ret.push_back(pll.back());
|
||||
ret.push_back(curP);
|
||||
} else {
|
||||
// careful, after push_back() below, lastIns might point to another
|
||||
// point because of reallocation
|
||||
*lastIns = iSect;
|
||||
|
||||
ret.push_back(curP);
|
||||
}
|
||||
} else {
|
||||
|
@ -249,8 +272,7 @@ Point<T> PolyLine<T>::interpolate(const Point<T>& a, const Point<T>& b,
|
|||
double n = sqrt(n1 * n1 + n2 * n2);
|
||||
n1 = n1 / n;
|
||||
n2 = n2 / n;
|
||||
return Point<T>(a.getX() + (n1 * p),
|
||||
a.getY() + (n2 * p));
|
||||
return Point<T>(a.getX() + (n1 * p), a.getY() + (n2 * p));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
|
@ -271,11 +293,39 @@ double PolyLine<T>::getLength() const {
|
|||
return len(_line);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
bool PolyLine<T>::shorterThan(double d) const {
|
||||
return util::geo::shorterThan(_line, d);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
bool PolyLine<T>::longerThan(double d) const {
|
||||
return util::geo::longerThan(_line, d);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
PolyLine<T> PolyLine<T>::average(const std::vector<const PolyLine<T>*>& lines,
|
||||
const std::vector<double>& weights) {
|
||||
bool weighted = lines.size() == weights.size();
|
||||
|
||||
if (!weighted && lines.size() == 2 && lines[0]->getLine().size() == 2 &&
|
||||
lines[1]->getLine().size() == 2) {
|
||||
// simple case
|
||||
util::geo::Line<T> avg(2);
|
||||
const auto& a = lines[0]->getLine();
|
||||
const auto& b = lines[1]->getLine();
|
||||
|
||||
avg[0] = {(a[0].getX() + b[0].getX()) / 2.0,
|
||||
(a[0].getY() + b[0].getY()) / 2.0};
|
||||
avg[1] = {(a[1].getX() + b[1].getX()) / 2.0,
|
||||
(a[1].getY() + b[1].getY()) / 2.0};
|
||||
|
||||
return avg;
|
||||
}
|
||||
|
||||
double stepSize;
|
||||
|
||||
double longestLength = DBL_MIN; // avoid recalc of length on each comparision
|
||||
|
@ -320,7 +370,7 @@ PolyLine<T> PolyLine<T>::average(const std::vector<const PolyLine<T>*>& lines,
|
|||
ret << Point<T>(x / total, y / total);
|
||||
}
|
||||
|
||||
ret.simplify(0);
|
||||
ret.simplify(0.0001);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -516,6 +566,12 @@ std::set<LinePoint<T>, LinePointCmp<T>> PolyLine<T>::getIntersections(
|
|||
return ret;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
PolyLine<T> PolyLine<T>::getOrthoLineAt(double d, double length) const {
|
||||
return getOrthoLineAtDist(getLength() * d, length);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
PolyLine<T> PolyLine<T>::getOrthoLineAtDist(double d, double length) const {
|
||||
|
@ -610,11 +666,9 @@ void PolyLine<T>::applyChaikinSmooth(size_t depth) {
|
|||
Point<T> pA = _line[i - 1];
|
||||
Point<T> pB = _line[i];
|
||||
|
||||
smooth.push_back(
|
||||
Point<T>(0.75 * pA.getX() + 0.25 * pB.getX(),
|
||||
smooth.push_back(Point<T>(0.75 * pA.getX() + 0.25 * pB.getX(),
|
||||
0.75 * pA.getY() + 0.25 * pB.getY()));
|
||||
smooth.push_back(
|
||||
Point<T>(0.25 * pA.getX() + 0.75 * pB.getX(),
|
||||
smooth.push_back(Point<T>(0.25 * pA.getX() + 0.75 * pB.getX(),
|
||||
0.25 * pA.getY() + 0.75 * pB.getY()));
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,12 @@ class Polygon {
|
|||
const Line<T>& getOuter() const { return _outer; }
|
||||
Line<T>& getOuter() { return _outer; }
|
||||
|
||||
const std::vector<Line<T>>& getInners() const { return _inners; }
|
||||
std::vector<Line<T>>& getInners() { return _inners; }
|
||||
|
||||
private:
|
||||
Line<T> _outer;
|
||||
std::vector<Line<T>> _inners;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
|
82
src/util/geo/RTree.h
Normal file
82
src/util/geo/RTree.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
// Copyright 2023, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Author: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#ifndef UTIL_GEO_RTREE_H_
|
||||
#define UTIL_GEO_RTREE_H_
|
||||
|
||||
#include <unordered_map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include "util/3rdparty/RTree.h"
|
||||
|
||||
namespace util {
|
||||
namespace geo {
|
||||
|
||||
class RTreeException : public std::runtime_error {
|
||||
public:
|
||||
RTreeException(std::string const& msg) : std::runtime_error(msg) {}
|
||||
};
|
||||
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
class RTree {
|
||||
public:
|
||||
// RTree(const RTree<V, G, T>&) = delete;
|
||||
// RTree(RTree<V, G, T>&& o) = delete;
|
||||
|
||||
// the empty RTree
|
||||
RTree() : _rtree(new DA::RTree<V, T, 2, T>()) {};
|
||||
|
||||
~RTree() {if (_rtree) delete _rtree;};
|
||||
|
||||
RTree(const RTree<V, G, T>&) = delete;
|
||||
RTree(RTree<V, G, T>&& o) {
|
||||
_valIdx = std::move(o._valIdx);
|
||||
_rtree = o._rtree;
|
||||
o._rtree = 0;
|
||||
}
|
||||
|
||||
RTree<V, G, T>& operator=(RTree<V, G, T>&& o) {
|
||||
_valIdx = std::move(o._valIdx);
|
||||
_rtree = o._rtree;
|
||||
o._rtree = 0;
|
||||
|
||||
return *this;
|
||||
};
|
||||
|
||||
// add object t to this RTree
|
||||
void add(G<T> geom, V val);
|
||||
|
||||
void get(const Box<T>& btbox, std::set<V>* s) const;
|
||||
|
||||
template <template <typename> class GG>
|
||||
void get(const GG<T>& geom, double d, std::set<V>* s) const;
|
||||
|
||||
template <template <typename> class GG>
|
||||
void get(const std::vector<GG<T>>& geom, double d, std::set<V>* s) const;
|
||||
|
||||
void get(const Box<T>& btbox, std::vector<V>* s) const;
|
||||
|
||||
template <template <typename> class GG>
|
||||
void get(const GG<T>& geom, double d, std::vector<V>* s) const;
|
||||
|
||||
template <template <typename> class GG>
|
||||
void get(const std::vector<GG<T>>& geom, double d, std::vector<V>* s) const;
|
||||
|
||||
void remove(V val);
|
||||
|
||||
void getNeighbors(const V& val, double d, std::set<V>* s) const;
|
||||
private:
|
||||
DA::RTree<V, T, 2, T>* _rtree = 0;
|
||||
|
||||
std::unordered_map<V, util::geo::Box<T>> _valIdx;
|
||||
|
||||
static bool searchCb(V val, void* arg);
|
||||
};
|
||||
|
||||
#include "util/geo/RTree.tpp"
|
||||
|
||||
} // namespace geo
|
||||
} // namespace util
|
||||
|
||||
#endif // UTIL_GEO_RTREE_H_
|
134
src/util/geo/RTree.tpp
Normal file
134
src/util/geo/RTree.tpp
Normal file
|
@ -0,0 +1,134 @@
|
|||
// Copyright 2023, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Author: Patrick Brosi <brosip@informatik.uni-freiburg.de>
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
void RTree<V, G, T>::add(G<T> geom, V val) {
|
||||
Box<T> box = getBoundingBox(geom);
|
||||
|
||||
T minCoords[2];
|
||||
T maxCoords[2];
|
||||
|
||||
minCoords[0] = box.getLowerLeft().getX();
|
||||
minCoords[1] = box.getLowerLeft().getY();
|
||||
|
||||
maxCoords[0] = box.getUpperRight().getX();
|
||||
maxCoords[1] = box.getUpperRight().getY();
|
||||
|
||||
if (_valIdx.count(val)) assert(false);
|
||||
|
||||
_valIdx[val] = box;
|
||||
|
||||
_rtree->Insert(minCoords, maxCoords, val);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
bool RTree<V, G, T>::searchCb(V val, void* s) {
|
||||
static_cast<std::set<V>*>(s)->insert(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
void RTree<V, G, T>::get(const Box<T>& box, std::set<V>* s) const {
|
||||
T minCoords[2];
|
||||
T maxCoords[2];
|
||||
|
||||
minCoords[0] = box.getLowerLeft().getX();
|
||||
minCoords[1] = box.getLowerLeft().getY();
|
||||
|
||||
maxCoords[0] = box.getUpperRight().getX();
|
||||
maxCoords[1] = box.getUpperRight().getY();
|
||||
|
||||
std::function<bool(const V&)> f = [s](const V& val) {
|
||||
s->insert(val);
|
||||
return true;
|
||||
};
|
||||
_rtree->Search(minCoords, maxCoords, f);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
void RTree<V, G, T>::get(const Box<T>& box, std::vector<V>* s) const {
|
||||
T minCoords[2];
|
||||
T maxCoords[2];
|
||||
|
||||
minCoords[0] = box.getLowerLeft().getX();
|
||||
minCoords[1] = box.getLowerLeft().getY();
|
||||
|
||||
maxCoords[0] = box.getUpperRight().getX();
|
||||
maxCoords[1] = box.getUpperRight().getY();
|
||||
|
||||
std::function<bool(const V&)> f = [s](const V& val) {
|
||||
s->push_back(val);
|
||||
return true;
|
||||
};
|
||||
_rtree->Search(minCoords, maxCoords, f);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
void RTree<V, G, T>::remove(V val) {
|
||||
auto bit = _valIdx.find(val);
|
||||
if (bit == _valIdx.end()) return;
|
||||
|
||||
Box<T> box = bit->second;
|
||||
|
||||
T minCoords[2];
|
||||
T maxCoords[2];
|
||||
|
||||
minCoords[0] = box.getLowerLeft().getX();
|
||||
minCoords[1] = box.getLowerLeft().getY();
|
||||
|
||||
maxCoords[0] = box.getUpperRight().getX();
|
||||
maxCoords[1] = box.getUpperRight().getY();
|
||||
|
||||
_valIdx.erase(bit);
|
||||
|
||||
bool notFound = _rtree->Remove(minCoords, maxCoords, val);
|
||||
assert(!notFound);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
template <template <typename> class GG>
|
||||
void RTree<V, G, T>::get(const GG<T>& geom, double d, std::set<V>* s) const {
|
||||
return get(util::geo::pad(getBoundingBox(geom), d), s);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
template <template <typename> class GG>
|
||||
void RTree<V, G, T>::get(const std::vector<GG<T>>& geom, double d,
|
||||
std::set<V>* s) const {
|
||||
return get(util::geo::pad(getBoundingBox(geom), d), s);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
template <template <typename> class GG>
|
||||
void RTree<V, G, T>::get(const GG<T>& geom, double d, std::vector<V>* s) const {
|
||||
return get(util::geo::pad(getBoundingBox(geom), d), s);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
template <template <typename> class GG>
|
||||
void RTree<V, G, T>::get(const std::vector<GG<T>>& geom, double d,
|
||||
std::vector<V>* s) const {
|
||||
return get(util::geo::pad(getBoundingBox(geom), d), s);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename V, template <typename> class G, typename T>
|
||||
void RTree<V, G, T>::getNeighbors(const V& val, double d,
|
||||
std::set<V>* s) const {
|
||||
auto bit = _valIdx.find(val);
|
||||
if (bit == _valIdx.end()) return;
|
||||
|
||||
Box<T> box = util::geo::pad(bit->second, d);
|
||||
|
||||
return get(box, s);
|
||||
}
|
|
@ -36,6 +36,15 @@ class GeoGraphJsonOutput {
|
|||
void printLatLng(const util::graph::Graph<N, E>& outG, std::ostream& str,
|
||||
json::Val attrs);
|
||||
|
||||
// print a graph to the provided GeoJsonOutput, but treat coordinates as Web Mercator
|
||||
// coordinates and reproject to WGS84
|
||||
template <typename N, typename E>
|
||||
void printLatLng(const util::graph::Graph<N, E>& outG, GeoJsonOutput* out);
|
||||
|
||||
// print a graph to the provided GeoJsonOutput
|
||||
template <typename N, typename E>
|
||||
void print(const util::graph::Graph<N, E>& outG, GeoJsonOutput* out);
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
Line<T> createLine(const util::geo::Point<T>& a,
|
||||
|
@ -45,6 +54,11 @@ class GeoGraphJsonOutput {
|
|||
template <typename N, typename E>
|
||||
void printImpl(const util::graph::Graph<N, E>& outG, std::ostream& str,
|
||||
bool proj, json::Val attrs);
|
||||
|
||||
// print a graph to the provided path
|
||||
template <typename N, typename E>
|
||||
void printImpl(const util::graph::Graph<N, E>& outG,
|
||||
bool proj, GeoJsonOutput* out);
|
||||
};
|
||||
|
||||
#include "util/geo/output/GeoGraphJsonOutput.tpp"
|
||||
|
|
|
@ -40,13 +40,34 @@ void GeoGraphJsonOutput::printLatLng(const util::graph::Graph<N, E>& outG,
|
|||
printImpl(outG, str, true, attrs);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
void GeoGraphJsonOutput::printLatLng(const util::graph::Graph<N, E>& outG,
|
||||
GeoJsonOutput* out) {
|
||||
printImpl(outG, true, out);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
void GeoGraphJsonOutput::print(const util::graph::Graph<N, E>& outG,
|
||||
GeoJsonOutput* out) {
|
||||
printImpl(outG, false, out);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
void GeoGraphJsonOutput::printImpl(const util::graph::Graph<N, E>& outG,
|
||||
std::ostream& str, bool proj, json::Val attrs) {
|
||||
|
||||
GeoJsonOutput _out(str, attrs);
|
||||
std::ostream& str, bool proj,
|
||||
json::Val attrs) {
|
||||
GeoJsonOutput out(str, attrs);
|
||||
printImpl(outG, proj, &out);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
void GeoGraphJsonOutput::printImpl(const util::graph::Graph<N, E>& outG,
|
||||
bool proj, GeoJsonOutput* out) {
|
||||
// first pass, nodes
|
||||
for (util::graph::Node<N, E>* n : outG.getNds()) {
|
||||
if (!n->pl().getGeom()) continue;
|
||||
|
@ -60,9 +81,9 @@ void GeoGraphJsonOutput::printImpl(const util::graph::Graph<N, E>& outG,
|
|||
props.insert(addProps.begin(), addProps.end());
|
||||
|
||||
if (proj) {
|
||||
_out.printLatLng(*n->pl().getGeom(), props);
|
||||
out->printLatLng(*n->pl().getGeom(), props);
|
||||
} else {
|
||||
_out.print(*n->pl().getGeom(), props);
|
||||
out->print(*n->pl().getGeom(), props);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,21 +105,19 @@ void GeoGraphJsonOutput::printImpl(const util::graph::Graph<N, E>& outG,
|
|||
if (e->getTo()->pl().getGeom()) {
|
||||
auto b = *e->getTo()->pl().getGeom();
|
||||
if (proj) {
|
||||
_out.printLatLng(createLine(a, b), props);
|
||||
out->printLatLng(createLine(a, b), props);
|
||||
} else {
|
||||
_out.print(createLine(a, b), props);
|
||||
out->print(createLine(a, b), props);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (proj) {
|
||||
_out.printLatLng(*e->pl().getGeom(), props);
|
||||
out->printLatLng(*e->pl().getGeom(), props);
|
||||
} else {
|
||||
_out.print(*e->pl().getGeom(), props);
|
||||
out->print(*e->pl().getGeom(), props);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_out.flush();
|
||||
}
|
||||
|
|
|
@ -9,11 +9,16 @@ using namespace geo;
|
|||
using namespace output;
|
||||
|
||||
// _____________________________________________________________________________
|
||||
GeoJsonOutput::GeoJsonOutput(std::ostream& str) : _wr(&str, 10, true) {
|
||||
GeoJsonOutput::GeoJsonOutput(std::ostream& str) : GeoJsonOutput(str, false) {}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
GeoJsonOutput::GeoJsonOutput(std::ostream& str, bool raw) : _wr(&str, 10, true) {
|
||||
if (!raw) {
|
||||
_wr.obj();
|
||||
_wr.keyVal("type", "FeatureCollection");
|
||||
_wr.key("features");
|
||||
_wr.arr();
|
||||
}
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
|
|
|
@ -19,12 +19,16 @@ namespace output {
|
|||
class GeoJsonOutput {
|
||||
public:
|
||||
GeoJsonOutput(std::ostream& str);
|
||||
GeoJsonOutput(std::ostream& str, bool raw);
|
||||
GeoJsonOutput(std::ostream& str, json::Val attrs);
|
||||
~GeoJsonOutput();
|
||||
|
||||
template <typename T>
|
||||
void print(const Point<T>& p, json::Val attrs);
|
||||
|
||||
template <typename T>
|
||||
void print(const MultiPoint<T>& ps, json::Val attrs);
|
||||
|
||||
template <typename T>
|
||||
void print(const Line<T>& l, json::Val attrs);
|
||||
|
||||
|
@ -40,6 +44,9 @@ class GeoJsonOutput {
|
|||
template <typename T>
|
||||
void printLatLng(const Point<T>& p, json::Val attrs);
|
||||
|
||||
template <typename T>
|
||||
void printLatLng(const MultiPoint<T>& ps, json::Val attrs);
|
||||
|
||||
template <typename T>
|
||||
void printLatLng(const Line<T>& l, json::Val attrs);
|
||||
|
||||
|
|
|
@ -22,6 +22,31 @@ void GeoJsonOutput::print(const Point<T>& p, json::Val attrs) {
|
|||
_wr.close();
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
void GeoJsonOutput::print(const MultiPoint<T>& ps, json::Val attrs) {
|
||||
if (!ps.size()) return;
|
||||
_wr.obj();
|
||||
_wr.keyVal("type", "Feature");
|
||||
|
||||
_wr.key("geometry");
|
||||
_wr.obj();
|
||||
_wr.keyVal("type", "MultiPoint");
|
||||
_wr.key("coordinates");
|
||||
_wr.arr();
|
||||
for (auto p : ps) {
|
||||
_wr.arr();
|
||||
_wr.val(p.getX());
|
||||
_wr.val(p.getY());
|
||||
_wr.close();
|
||||
}
|
||||
_wr.close();
|
||||
_wr.close();
|
||||
_wr.key("properties");
|
||||
_wr.val(attrs);
|
||||
_wr.close();
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
void GeoJsonOutput::print(const Line<T>& line, json::Val attrs) {
|
||||
|
@ -65,6 +90,7 @@ void GeoJsonOutput::print(const Polygon<T>& poly, json::Val attrs) {
|
|||
_wr.keyVal("type", "Polygon");
|
||||
_wr.key("coordinates");
|
||||
_wr.arr();
|
||||
|
||||
_wr.arr();
|
||||
for (auto p : poly.getOuter()) {
|
||||
_wr.arr();
|
||||
|
@ -72,8 +98,19 @@ void GeoJsonOutput::print(const Polygon<T>& poly, json::Val attrs) {
|
|||
_wr.val(p.getY());
|
||||
_wr.close();
|
||||
}
|
||||
|
||||
_wr.close();
|
||||
|
||||
for (const auto& inner : poly.getInners()) {
|
||||
_wr.arr();
|
||||
for (auto p : inner) {
|
||||
_wr.arr();
|
||||
_wr.val(p.getX());
|
||||
_wr.val(p.getY());
|
||||
_wr.close();
|
||||
}
|
||||
_wr.close();
|
||||
}
|
||||
|
||||
_wr.close();
|
||||
_wr.close();
|
||||
_wr.key("properties");
|
||||
|
@ -90,16 +127,26 @@ void GeoJsonOutput::print(const MultiPolygon<T>& mpoly, json::Val attrs) {
|
|||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
void GeoJsonOutput::printLatLng(const Point<T>& p, json::Val attrs) {
|
||||
auto projP = util::geo::webMercToLatLng<double>(p.getX(), p.getY());
|
||||
auto projP = util::geo::webMercToLatLng<T>(p.getX(), p.getY());
|
||||
print(projP, attrs);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
void GeoJsonOutput::printLatLng(const MultiPoint<T>& ps, json::Val attrs) {
|
||||
MultiPoint<T> projPs;
|
||||
for (auto p : ps)
|
||||
projPs.push_back(util::geo::webMercToLatLng<T>(p.getX(), p.getY()));
|
||||
|
||||
print(projPs, attrs);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename T>
|
||||
void GeoJsonOutput::printLatLng(const Line<T>& line, json::Val attrs) {
|
||||
Line<T> projL;
|
||||
for (auto p : line)
|
||||
projL.push_back(util::geo::webMercToLatLng<double>(p.getX(), p.getY()));
|
||||
projL.push_back(util::geo::webMercToLatLng<T>(p.getX(), p.getY()));
|
||||
|
||||
print(projL, attrs);
|
||||
}
|
||||
|
@ -114,8 +161,8 @@ void GeoJsonOutput::printLatLng(const MultiLine<T>& mline, json::Val attrs) {
|
|||
template <typename T>
|
||||
void GeoJsonOutput::printLatLng(const Polygon<T>& poly, json::Val attrs) {
|
||||
Polygon<T> projP;
|
||||
for (auto p : poly)
|
||||
projP.push_back(util::geo::webMercToLatLng<double>(p.getX(), p.getY()));
|
||||
for (auto p : poly.getOuter())
|
||||
projP.getOuter().push_back(util::geo::webMercToLatLng<T>(p.getX(), p.getY()));
|
||||
|
||||
print(projP, attrs);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ class DirGraph : public Graph<N, E> {
|
|||
Node<N, E>* addNd(DirNode<N, E>* n);
|
||||
Node<N, E>* addNd(const N& pl);
|
||||
Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to, const E& p);
|
||||
Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to, E&& p);
|
||||
|
||||
virtual Node<N, E>* mergeNds(Node<N, E>* a, Node<N, E>* b);
|
||||
|
||||
|
|
|
@ -34,6 +34,18 @@ Edge<N, E>* DirGraph<N, E>::addEdg(Node<N, E>* from, Node<N, E>* to,
|
|||
return e;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Edge<N, E>* DirGraph<N, E>::addEdg(Node<N, E>* from, Node<N, E>* to, E&& p) {
|
||||
Edge<N, E>* e = Graph<N, E>::getEdg(from, to);
|
||||
if (!e) {
|
||||
e = new Edge<N, E>(from, to, p);
|
||||
from->addEdge(e);
|
||||
to->addEdge(e);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Node<N, E>* DirGraph<N, E>::mergeNds(Node<N, E>* a, Node<N, E>* b) {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#define UTIL_GRAPH_EDGE_H_
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include "util/graph/Node.h"
|
||||
|
||||
namespace util {
|
||||
|
@ -15,6 +16,7 @@ template <typename N, typename E>
|
|||
class Edge {
|
||||
public:
|
||||
Edge(Node<N, E>* from, Node<N, E>* to, const E& pl);
|
||||
Edge(Node<N, E>* from, Node<N, E>* to, E&& pl);
|
||||
|
||||
Node<N, E>* getFrom() const;
|
||||
Node<N, E>* getTo() const;
|
||||
|
|
|
@ -6,7 +6,12 @@
|
|||
template <typename N, typename E>
|
||||
Edge<N, E>::Edge(Node<N, E>* from, Node<N, E>* to, const E& pl)
|
||||
: _from(from), _to(to), _pl(pl) {
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Edge<N, E>::Edge(Node<N, E>* from, Node<N, E>* to, E&& pl)
|
||||
: _from(from), _to(to), _pl(std::move(pl)) {
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
|
|
|
@ -19,11 +19,17 @@ namespace graph {
|
|||
template <typename N, typename E>
|
||||
class Graph {
|
||||
public:
|
||||
Graph() {} ;
|
||||
Graph(const Graph& g) = delete;
|
||||
Graph(Graph& g) = delete;
|
||||
void operator=(const Graph& other) = delete;
|
||||
void operator=(Graph& other) = delete;
|
||||
virtual ~Graph();
|
||||
virtual Node<N, E>* addNd() = 0;
|
||||
virtual Node<N, E>* addNd(const N& pl) = 0;
|
||||
Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to);
|
||||
virtual Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to, const E& p) = 0;
|
||||
virtual Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to, E&& p) = 0;
|
||||
Edge<N, E>* getEdg(Node<N, E>* from, Node<N, E>* to);
|
||||
const Edge<N, E>* getEdg(const Node<N, E>* from, const Node<N, E>* to) const;
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ class UndirGraph : public Graph<N, E> {
|
|||
Node<N, E>* addNd(UndirNode<N, E>* n);
|
||||
Node<N, E>* addNd(const N& pl);
|
||||
Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to, const E& p);
|
||||
Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to, E&& p);
|
||||
|
||||
virtual Node<N, E>* mergeNds(Node<N, E>* a, Node<N, E>* b);
|
||||
|
||||
|
|
|
@ -38,6 +38,19 @@ Edge<N, E>* UndirGraph<N, E>::addEdg(Node<N, E>* from, Node<N, E>* to,
|
|||
return e;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Edge<N, E>* UndirGraph<N, E>::addEdg(Node<N, E>* from, Node<N, E>* to,
|
||||
E&& p) {
|
||||
Edge<N, E>* e = Graph<N, E>::getEdg(from, to);
|
||||
if (!e) {
|
||||
e = new Edge<N, E>(from, to, std::move(p));
|
||||
from->addEdge(e);
|
||||
to->addEdge(e);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Node<N, E>* UndirGraph<N, E>::mergeNds(Node<N, E>* a, Node<N, E>* b) {
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#endif
|
||||
#include <vector>
|
||||
#include "Server.h"
|
||||
#include "util/Misc.h"
|
||||
#include "util/String.h"
|
||||
#include "util/log/Log.h"
|
||||
|
||||
|
@ -110,7 +109,11 @@ void HttpServer::handle() {
|
|||
try {
|
||||
Req req = getReq(connection);
|
||||
answ = _handler->handle(req, connection);
|
||||
answ.gzip = gzipSupport(req);
|
||||
if (answ.raw) {
|
||||
close(connection); // the handle did everything
|
||||
continue;
|
||||
}
|
||||
answ.gzip = req.gzip;
|
||||
} catch (const HttpErr& err) {
|
||||
answ = Answer(err.what(), err.what());
|
||||
} catch (...) {
|
||||
|
@ -277,6 +280,7 @@ Req HttpServer::getReq(int connection) {
|
|||
}
|
||||
}
|
||||
|
||||
ret.gzip = gzipSupport(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace http {
|
|||
// socket backlog size
|
||||
const static size_t BLOG = 128;
|
||||
// socket read buffer size
|
||||
const static size_t BSIZE = 4 * 1024;
|
||||
const static size_t BSIZE = 16 * 1024;
|
||||
// zlib compression buffer size
|
||||
const size_t BSIZE_C = 128 * 1024;
|
||||
|
||||
|
@ -56,6 +56,7 @@ class HttpErr : public std::exception {
|
|||
struct Req {
|
||||
std::string cmd, url, ver, payload;
|
||||
std::unordered_map<std::string, std::string> params;
|
||||
bool gzip = false;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -68,7 +69,8 @@ struct Answer {
|
|||
Answer(const std::string& status, const std::string& pl, bool gz)
|
||||
: status(status), pl(pl), gzip(gz) {}
|
||||
std::string status, pl;
|
||||
bool gzip;
|
||||
bool gzip = false;
|
||||
bool raw = false;
|
||||
std::unordered_map<std::string, std::string> params;
|
||||
};
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
#include "Writer.h"
|
||||
#include "util/String.h"
|
||||
using namespace util;
|
||||
|
@ -95,7 +96,13 @@ void Writer::val(uint64_t v) {
|
|||
// _____________________________________________________________________________
|
||||
void Writer::val(double v) {
|
||||
valCheck();
|
||||
if (v > std::numeric_limits<double>::max())
|
||||
*_out << std::numeric_limits<double>::max();
|
||||
else if (std::isnan(v))
|
||||
*_out << "NaN";
|
||||
else {
|
||||
*_out << std::fixed << std::setprecision(_floatPrec) << v;
|
||||
}
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "util/tests/QuadTreeTest.h"
|
||||
#include "util/geo/Geo.h"
|
||||
#include "util/geo/Grid.h"
|
||||
#include "util/geo/RTree.h"
|
||||
#include "util/graph/Algorithm.h"
|
||||
#include "util/graph/Dijkstra.h"
|
||||
#include "util/graph/BiDijkstra.h"
|
||||
|
@ -265,6 +266,64 @@ int main(int argc, char** argv) {
|
|||
g.getNeighbors(1, 0.55, &ret);
|
||||
TEST(ret.size(), ==, (size_t)2);
|
||||
|
||||
g.remove(1);
|
||||
ret.clear();
|
||||
g.getNeighbors(1, 0, &ret);
|
||||
TEST(ret.size(), ==, (size_t)0);
|
||||
|
||||
g.remove(2);
|
||||
ret.clear();
|
||||
g.getNeighbors(1, 10, &ret);
|
||||
TEST(ret.size(), ==, (size_t)0);
|
||||
|
||||
// TODO: more test cases
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
{
|
||||
RTree<int, Line, double> g;
|
||||
|
||||
Line<double> l;
|
||||
l.push_back(Point<double>(0, 0));
|
||||
l.push_back(Point<double>(1.5, 2));
|
||||
|
||||
Line<double> l2;
|
||||
l2.push_back(Point<double>(2.5, 1));
|
||||
l2.push_back(Point<double>(2.5, 2));
|
||||
|
||||
g.add(l, 1);
|
||||
g.add(l2, 2);
|
||||
|
||||
std::set<int> ret;
|
||||
|
||||
Box<double> req(Point<double>(.5, 1), Point<double>(1, 1.5));
|
||||
g.get(req, &ret);
|
||||
TEST(ret.size(), ==, (size_t)1);
|
||||
|
||||
ret.clear();
|
||||
Box<double> req2(Point<double>(.5, 1), Point<double>(2.5, 2));
|
||||
g.get(req2, &ret);
|
||||
TEST(ret.size(), ==, (size_t)2);
|
||||
|
||||
ret.clear();
|
||||
g.getNeighbors(1, 0, &ret);
|
||||
TEST(ret.size(), ==, (size_t)1);
|
||||
|
||||
ret.clear();
|
||||
g.getNeighbors(1, 1.55, &ret);
|
||||
TEST(ret.size(), ==, (size_t)2);
|
||||
|
||||
|
||||
g.remove(1);
|
||||
ret.clear();
|
||||
g.getNeighbors(1, 0, &ret);
|
||||
TEST(ret.size(), ==, (size_t)0);
|
||||
|
||||
g.remove(2);
|
||||
ret.clear();
|
||||
g.getNeighbors(1, 10, &ret);
|
||||
TEST(ret.size(), ==, (size_t)0);
|
||||
|
||||
// TODO: more test cases
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue