1
#include "valhalla/midgard/util.h"
2
#include "valhalla/midgard/constants.h"
3
#include "valhalla/midgard/point2.h"
4
#include "valhalla/midgard/distanceapproximator.h"
17
constexpr double RAD_PER_METER = 1.0 / 6378160.187;
18
constexpr double RAD_PER_DEG = valhalla::midgard::kPiDouble / 180.0;
19
constexpr double DEG_PER_RAD = 180.0 / valhalla::midgard::kPiDouble;
26
int GetTime(const float length, const float speed) {
28
return (int)(length / (speed * kHourPerSec) + 0.5f);
32
uint32_t GetTurnDegree(const uint32_t from_heading, const uint32_t to_heading) {
33
return (((to_heading - from_heading) + 360) % 360);
37
return (float)rand() / (float)RAND_MAX;
40
float FastInvSqrt(float x) {
41
float xhalf = 0.5f * x;
42
int i = *(int*)&x; // get bits for floating value
43
i = 0x5f3759df - (i >> 1); // give initial guess y0
44
x = *(float*)&i; // convert bits back to float
45
return x * (1.5f - xhalf * x * x); // newton step
46
// x *= 1.5f - xhalf*x*x; // repeating step increases accuracy
49
// Trim the front of a polyline (represented as a list or vector of Point2).
50
// Returns the trimmed portion of the polyline. The supplied polyline is
51
// altered (the trimmed part is removed).
52
template <class container_t>
53
container_t trim_front(container_t& pts, const float dist) {
54
// Return if less than 2 points
59
// Walk the polyline and accumulate length until it exceeds dist
61
result.push_back(pts.front());
63
for (auto p1 = pts.begin(), p2 = std::next(pts.begin()); p2 != pts.end(); ++p1, ++p2) {
64
double segdist = p1->Distance(*p2);
65
if ((d + segdist) > dist) {
66
double frac = (dist - d) / segdist;
67
auto midpoint = p1->AffineCombination((1.0-frac), frac, *p2);
68
result.push_back(midpoint);
70
// Remove used part of polyline
71
pts.erase(pts.begin(), p1);
72
pts.front() = midpoint;
76
result.push_back(*p2);
80
// Used all of the polyline without exceeding dist
85
// Explicit instantiations
86
template std::vector<PointLL> trim_front<std::vector<PointLL> >(std::vector<PointLL>&, const float);
87
template std::vector<Point2> trim_front<std::vector<Point2> >(std::vector<Point2>&, const float);
88
template std::list<PointLL> trim_front<std::list<PointLL> >(std::list<PointLL>&, const float);
89
template std::list<Point2> trim_front<std::list<Point2> >(std::list<Point2>&, const float);
91
memory_status::memory_status(const std::unordered_set<std::string> interest){
92
//grab the vm stats from the file
93
std::ifstream file("/proc/self/status");
95
while(std::getline(file, line)){
96
//did we find a memory metric
97
if(line.find_first_of("Vm") == 0){
98
//grab the name of it and see if we care about it
99
std::string name = line.substr(0, line.find_first_of(':'));
100
if(interest.size() > 0 && interest.find(name) == interest.end())
102
//try to get the number of bytes
103
std::remove_if(line.begin(), line.end(), [](const char c) {return !std::isdigit(c);});
106
auto bytes = std::stod(line) * 1024.0;
107
//get the units and scale
108
std::pair<double, std::string> metric = std::make_pair(bytes, "b");
109
for(auto unit : { "B", "KB", "MB", "GB" }){
110
metric.second = unit;
111
if (metric.first > 1024.0)
112
metric.first /= 1024.0;
116
metrics.emplace(std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(metric));
122
bool memory_status::supported() {
124
return stat("/proc/self/status", &s) == 0;
127
std::ostream& operator<<(std::ostream& stream, const memory_status& s){
128
for(const auto& metric : s.metrics)
129
stream << metric.first << ": " << metric.second.first << metric.second.second << std::endl;
133
/* This method makes use of several computations explained and demonstrated at:
134
* http://williams.best.vwh.net/avform.htm *
135
* We humbly bow to you sir!
137
template <class container_t>
138
container_t resample_spherical_polyline(const container_t& polyline, double resolution, bool preserve) {
139
if(polyline.size() == 0)
143
container_t resampled = {polyline.front()};
144
resolution *= RAD_PER_METER;
145
double remaining = resolution;
146
PointLL last = resampled.back();
147
for(auto p = std::next(polyline.cbegin()); p != polyline.cend(); ++p) {
149
auto lon2 = p->first * -RAD_PER_DEG;
150
auto lat2 = p->second * RAD_PER_DEG;
151
//how much do we have left on this segment from where we are (in great arc radians)
152
//double d = 2.0 * asin(sqrt(pow(sin((resampled.back().second * RAD_PER_DEG - lat2) / 2.0), 2.0) + cos(resampled.back().second * RAD_PER_DEG) * cos(lat2) *pow(sin((resampled.back().first * -RAD_PER_DEG - lon2) / 2.0), 2.0)));
154
sin(last.second * RAD_PER_DEG) * sin(lat2) +
155
cos(last.second * RAD_PER_DEG) * cos(lat2) *
156
cos(last.first * -RAD_PER_DEG - lon2)
158
//keep placing points while we can fit them
159
while(d > remaining) {
160
//some precomputed stuff
161
auto lon1 = last.first * -RAD_PER_DEG;
162
auto lat1 = last.second * RAD_PER_DEG;
164
auto a = sin(d - remaining) / sd;
165
auto acs1 = a * cos(lat1);
166
auto b = sin(remaining) / sd;
167
auto bcs2 = b * cos(lat2);
168
//find the interpolated point along the arc
169
auto x = acs1 * cos(lon1) + bcs2 * cos(lon2);
170
auto y = acs1 * sin(lon1) + bcs2 * sin(lon2);
171
auto z = a * sin(lat1) + b * sin(lat2);
172
last.first = atan2(y, x) * -DEG_PER_RAD;
173
last.second = atan2(z, sqrt(x * x + y * y)) * DEG_PER_RAD;
174
resampled.push_back(last);
175
//we just consumed a bit
177
//we need another bit
178
remaining = resolution;
180
//we're going to the next point so consume whatever's left
184
resampled.push_back(last);
187
//TODO: do we want to let them know remaining?
193
//explicit instantiations
194
template std::vector<PointLL> resample_spherical_polyline<std::vector<PointLL> >(const std::vector<PointLL>&, double, bool);
195
template std::vector<Point2> resample_spherical_polyline<std::vector<Point2> >(const std::vector<Point2>&, double, bool);
196
template std::list<PointLL> resample_spherical_polyline<std::list<PointLL> >(const std::list<PointLL>&, double, bool);
197
template std::list<Point2> resample_spherical_polyline<std::list<Point2> >(const std::list<Point2>&, double, bool);
199
//Return the intersection of two infinite lines if any
200
template <class coord_t>
201
bool intersect(const coord_t& u, const coord_t& v, const coord_t& a, const coord_t& b, coord_t& i) {
202
auto uv_xd = u.first - v.first;
203
auto uv_yd = u.second - v.second;
204
auto ab_xd = a.first - b.first;
205
auto ab_yd = a.second - b.second;
206
auto d_cross = uv_xd*ab_yd - ab_xd*uv_yd;
207
//parallel or very close to it
208
if(std::abs(d_cross) < 1e-5)
210
auto uv_cross = u.first*v.second - u.second*v.first;
211
auto ab_cross = a.first*b.second - a.second*b.first;
212
i.first = (uv_cross*ab_xd - uv_xd*ab_cross) / d_cross;
213
i.second = (uv_cross*ab_yd - uv_yd*ab_cross) / d_cross;
216
template bool intersect<PointLL>(const PointLL& u, const PointLL& v, const PointLL& a, const PointLL& b, PointLL& i);
217
template bool intersect<Point2>(const Point2& u, const Point2& v, const Point2& a, const Point2& b, Point2& i);
219
//Return the intercept of the line passing through uv with the horizontal line defined by y
220
template <class coord_t>
221
typename coord_t::first_type y_intercept(const coord_t& u, const coord_t& v, const typename coord_t::second_type y) {
222
if(std::abs(u.first - v.first) < 1e-5)
224
if(std::abs(u.second - u.second) < 1e-5)
226
auto m = (v.second - u.second) / (v.first - u.first);
227
auto b = u.second - (u.first * m);
230
template PointLL::first_type y_intercept<PointLL>(const PointLL& u, const PointLL& v, const PointLL::first_type y);
231
template Point2::first_type y_intercept<Point2>(const Point2& u, const Point2& v, const Point2::first_type y);
233
//Return the intercept of the line passing through uv with the vertical line defined by x
234
template <class coord_t>
235
typename coord_t::first_type x_intercept(const coord_t& u, const coord_t& v, const typename coord_t::second_type x) {
236
if(std::abs(u.second - v.second) < 1e-5)
238
if(std::abs(u.first - v.first) < 1e-5)
240
auto m = (v.second - u.second) / (v.first - u.first);
241
auto b = u.second - (u.first * m);
244
template PointLL::second_type x_intercept<PointLL>(const PointLL& u, const PointLL& v, const PointLL::second_type x);
245
template Point2::second_type x_intercept<Point2>(const Point2& u, const Point2& v, const Point2::second_type x);
247
template <class container_t>
248
float polygon_area(const container_t& polygon) {
249
typename container_t::value_type::first_type area = polygon.back() == polygon.front() ? 0.f :
250
(polygon.back().first + polygon.front().first)*(polygon.back().second + polygon.front().second);
251
for(auto p1 = polygon.cbegin(), p2 = std::next(polygon.cbegin()); p2 != polygon.cend(); ++p1, ++p2)
252
area += (p1->first + p2->first)*(p1->second + p2->second);
256
template PointLL::first_type polygon_area(const std::list<PointLL>&);
257
template PointLL::first_type polygon_area(const std::vector<PointLL>&);
258
template Point2::first_type polygon_area(const std::list<Point2>&);
259
template Point2::first_type polygon_area(const std::vector<Point2>&);