diff --git a/Algorithms/DouglasPeucker.cpp b/Algorithms/DouglasPeucker.cpp index afd833cccfb..6444f135753 100644 --- a/Algorithms/DouglasPeucker.cpp +++ b/Algorithms/DouglasPeucker.cpp @@ -108,38 +108,35 @@ DouglasPeucker::DouglasPeucker() void DouglasPeucker::Run(std::vector &input_geometry, const unsigned zoom_level) { - Run(std::begin(input_geometry), std::end(input_geometry), zoom_level); -} + // check if input data is invalid + BOOST_ASSERT_MSG(!input_geometry.empty(), "geometry invalid"); -void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level) -{ - unsigned size = std::distance(begin, end); - if (size < 2) + if (input_geometry.size() < 2) { return; } - begin->necessary = true; - std::prev(end)->necessary = true; + input_geometry.front().necessary = true; + input_geometry.back().necessary = true; { BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level"); - RandomAccessIt left_border = begin; - RandomAccessIt right_border = std::next(begin); + unsigned left_border = 0; + unsigned right_border = 1; // Sweep over array and identify those ranges that need to be checked do { // traverse list until new border element found - if (right_border->necessary) + if (input_geometry[right_border].necessary) { // sanity checks - BOOST_ASSERT(left_border->necessary); - BOOST_ASSERT(right_border->necessary); + BOOST_ASSERT(input_geometry[left_border].necessary); + BOOST_ASSERT(input_geometry[right_border].necessary); recursion_stack.emplace(left_border, right_border); left_border = right_border; } ++right_border; - } while (right_border != end); + } while (right_border < input_geometry.size()); } // mark locations as 'necessary' by divide-and-conquer @@ -149,23 +146,24 @@ void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigne const GeometryRange pair = recursion_stack.top(); recursion_stack.pop(); // sanity checks - BOOST_ASSERT_MSG(pair.first->necessary, "left border mus be necessary"); - BOOST_ASSERT_MSG(pair.second->necessary, "right border must be necessary"); - BOOST_ASSERT_MSG(std::distance(pair.second, end) > 0, "right border outside of geometry"); - BOOST_ASSERT_MSG(std::distance(pair.first, pair.second) >= 0, "left border on the wrong side"); + BOOST_ASSERT_MSG(input_geometry[pair.first].necessary, "left border mus be necessary"); + BOOST_ASSERT_MSG(input_geometry[pair.second].necessary, "right border must be necessary"); + BOOST_ASSERT_MSG(pair.second < input_geometry.size(), "right border outside of geometry"); + BOOST_ASSERT_MSG(pair.first < pair.second, "left border on the wrong side"); int max_int_distance = 0; - auto farthest_entry_it = pair.second; - const CoordinatePairCalculator dist_calc(pair.first->location, pair.second->location); + unsigned farthest_entry_index = pair.second; + const CoordinatePairCalculator dist_calc(input_geometry[pair.first].location, + input_geometry[pair.second].location); // sweep over range to find the maximum - for (auto it = std::next(pair.first); it != pair.second; ++it) + for (const auto i : osrm::irange(pair.first + 1, pair.second)) { - const int distance = dist_calc(it->location); + const int distance = dist_calc(input_geometry[i].location); // found new feasible maximum? if (distance > max_int_distance && distance > douglas_peucker_thresholds[zoom_level]) { - farthest_entry_it = it; + farthest_entry_index = i; max_int_distance = distance; } } @@ -174,14 +172,14 @@ void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigne if (max_int_distance > douglas_peucker_thresholds[zoom_level]) { // mark idx as necessary - farthest_entry_it->necessary = true; - if (1 < std::distance(pair.first, farthest_entry_it)) + input_geometry[farthest_entry_index].necessary = true; + if (1 < (farthest_entry_index - pair.first)) { - recursion_stack.emplace(pair.first, farthest_entry_it); + recursion_stack.emplace(pair.first, farthest_entry_index); } - if (1 < std::distance(pair.second, farthest_entry_it)) + if (1 < (pair.second - farthest_entry_index)) { - recursion_stack.emplace(farthest_entry_it, pair.second); + recursion_stack.emplace(farthest_entry_index, pair.second); } } } diff --git a/Algorithms/DouglasPeucker.h b/Algorithms/DouglasPeucker.h index b5146721ea7..60fc377b101 100644 --- a/Algorithms/DouglasPeucker.h +++ b/Algorithms/DouglasPeucker.h @@ -43,18 +43,15 @@ struct SegmentInformation; class DouglasPeucker { - public: - using RandomAccessIt = std::vector::iterator; private: std::vector douglas_peucker_thresholds; - using GeometryRange = std::pair; + using GeometryRange = std::pair; // Stack to simulate the recursion std::stack recursion_stack; public: DouglasPeucker(); - void Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level); void Run(std::vector &input_geometry, const unsigned zoom_level); }; diff --git a/DataStructures/Rectangle.h b/DataStructures/Rectangle.h deleted file mode 100644 index 7cbd31504ec..00000000000 --- a/DataStructures/Rectangle.h +++ /dev/null @@ -1,172 +0,0 @@ -#ifndef RECTANGLE_H -#define RECTANGLE_H - -#include - -#include -#include -#include - -// TODO: Make template type, add tests -struct RectangleInt2D -{ - RectangleInt2D() : min_lon(std::numeric_limits::max()), - max_lon(std::numeric_limits::min()), - min_lat(std::numeric_limits::max()), - max_lat(std::numeric_limits::min()) {} - - int32_t min_lon, max_lon; - int32_t min_lat, max_lat; - - inline void MergeBoundingBoxes(const RectangleInt2D &other) - { - min_lon = std::min(min_lon, other.min_lon); - max_lon = std::max(max_lon, other.max_lon); - min_lat = std::min(min_lat, other.min_lat); - max_lat = std::max(max_lat, other.max_lat); - BOOST_ASSERT(min_lat != std::numeric_limits::min()); - BOOST_ASSERT(min_lon != std::numeric_limits::min()); - BOOST_ASSERT(max_lat != std::numeric_limits::min()); - BOOST_ASSERT(max_lon != std::numeric_limits::min()); - } - - inline FixedPointCoordinate Centroid() const - { - FixedPointCoordinate centroid; - // The coordinates of the midpoints are given by: - // x = (x1 + x2) /2 and y = (y1 + y2) /2. - centroid.lon = (min_lon + max_lon) / 2; - centroid.lat = (min_lat + max_lat) / 2; - return centroid; - } - - inline bool Intersects(const RectangleInt2D &other) const - { - FixedPointCoordinate upper_left(other.max_lat, other.min_lon); - FixedPointCoordinate upper_right(other.max_lat, other.max_lon); - FixedPointCoordinate lower_right(other.min_lat, other.max_lon); - FixedPointCoordinate lower_left(other.min_lat, other.min_lon); - - return (Contains(upper_left) || Contains(upper_right) || Contains(lower_right) || - Contains(lower_left)); - } - - inline float GetMinDist(const FixedPointCoordinate &location) const - { - const bool is_contained = Contains(location); - if (is_contained) - { - return 0.0f; - } - - enum Direction - { - INVALID = 0, - NORTH = 1, - SOUTH = 2, - EAST = 4, - NORTH_EAST = 5, - SOUTH_EAST = 6, - WEST = 8, - NORTH_WEST = 9, - SOUTH_WEST = 10 - }; - - Direction d = INVALID; - if (location.lat > max_lat) - d = (Direction) (d | NORTH); - else if (location.lat < min_lat) - d = (Direction) (d | SOUTH); - if (location.lon > max_lon) - d = (Direction) (d | EAST); - else if (location.lon < min_lon) - d = (Direction) (d | WEST); - - BOOST_ASSERT(d != INVALID); - - float min_dist = std::numeric_limits::max(); - switch (d) - { - case NORTH: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, location.lon)); - break; - case SOUTH: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, location.lon)); - break; - case WEST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, min_lon)); - break; - case EAST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, max_lon)); - break; - case NORTH_EAST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, max_lon)); - break; - case NORTH_WEST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, min_lon)); - break; - case SOUTH_EAST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, max_lon)); - break; - case SOUTH_WEST: - min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, min_lon)); - break; - default: - break; - } - - BOOST_ASSERT(min_dist != std::numeric_limits::max()); - - return min_dist; - } - - inline float GetMinMaxDist(const FixedPointCoordinate &location) const - { - float min_max_dist = std::numeric_limits::max(); - // Get minmax distance to each of the four sides - const FixedPointCoordinate upper_left(max_lat, min_lon); - const FixedPointCoordinate upper_right(max_lat, max_lon); - const FixedPointCoordinate lower_right(min_lat, max_lon); - const FixedPointCoordinate lower_left(min_lat, min_lon); - - min_max_dist = std::min( - min_max_dist, - std::max( - FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left), - FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right))); - - min_max_dist = std::min( - min_max_dist, - std::max( - FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right), - FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right))); - - min_max_dist = std::min( - min_max_dist, - std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right), - FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left))); - - min_max_dist = std::min( - min_max_dist, - std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left), - FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left))); - return min_max_dist; - } - - inline bool Contains(const FixedPointCoordinate &location) const - { - const bool lats_contained = (location.lat >= min_lat) && (location.lat <= max_lat); - const bool lons_contained = (location.lon >= min_lon) && (location.lon <= max_lon); - return lats_contained && lons_contained; - } - - inline friend std::ostream &operator<<(std::ostream &out, const RectangleInt2D &rect) - { - out << rect.min_lat / COORDINATE_PRECISION << "," << rect.min_lon / COORDINATE_PRECISION - << " " << rect.max_lat / COORDINATE_PRECISION << "," - << rect.max_lon / COORDINATE_PRECISION; - return out; - } -}; - -#endif diff --git a/DataStructures/StaticRTree.h b/DataStructures/StaticRTree.h index ef4fc2d8b65..62e194e6689 100644 --- a/DataStructures/StaticRTree.h +++ b/DataStructures/StaticRTree.h @@ -32,7 +32,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "HilbertValue.h" #include "PhantomNodes.h" #include "QueryNode.h" -#include "Rectangle.h" #include "SharedMemoryFactory.h" #include "SharedMemoryVectorWrapper.h" @@ -71,6 +70,190 @@ template &objects, + const uint32_t element_count, + const std::vector &coordinate_list) + { + for (uint32_t i = 0; i < element_count; ++i) + { + min_lon = std::min(min_lon, + std::min(coordinate_list.at(objects[i].u).lon, + coordinate_list.at(objects[i].v).lon)); + max_lon = std::max(max_lon, + std::max(coordinate_list.at(objects[i].u).lon, + coordinate_list.at(objects[i].v).lon)); + + min_lat = std::min(min_lat, + std::min(coordinate_list.at(objects[i].u).lat, + coordinate_list.at(objects[i].v).lat)); + max_lat = std::max(max_lat, + std::max(coordinate_list.at(objects[i].u).lat, + coordinate_list.at(objects[i].v).lat)); + } + BOOST_ASSERT(min_lat != std::numeric_limits::min()); + BOOST_ASSERT(min_lon != std::numeric_limits::min()); + BOOST_ASSERT(max_lat != std::numeric_limits::min()); + BOOST_ASSERT(max_lon != std::numeric_limits::min()); + } + + inline void MergeBoundingBoxes(const RectangleInt2D &other) + { + min_lon = std::min(min_lon, other.min_lon); + max_lon = std::max(max_lon, other.max_lon); + min_lat = std::min(min_lat, other.min_lat); + max_lat = std::max(max_lat, other.max_lat); + BOOST_ASSERT(min_lat != std::numeric_limits::min()); + BOOST_ASSERT(min_lon != std::numeric_limits::min()); + BOOST_ASSERT(max_lat != std::numeric_limits::min()); + BOOST_ASSERT(max_lon != std::numeric_limits::min()); + } + + inline FixedPointCoordinate Centroid() const + { + FixedPointCoordinate centroid; + // The coordinates of the midpoints are given by: + // x = (x1 + x2) /2 and y = (y1 + y2) /2. + centroid.lon = (min_lon + max_lon) / 2; + centroid.lat = (min_lat + max_lat) / 2; + return centroid; + } + + inline bool Intersects(const RectangleInt2D &other) const + { + FixedPointCoordinate upper_left(other.max_lat, other.min_lon); + FixedPointCoordinate upper_right(other.max_lat, other.max_lon); + FixedPointCoordinate lower_right(other.min_lat, other.max_lon); + FixedPointCoordinate lower_left(other.min_lat, other.min_lon); + + return (Contains(upper_left) || Contains(upper_right) || Contains(lower_right) || + Contains(lower_left)); + } + + inline float GetMinDist(const FixedPointCoordinate &location) const + { + const bool is_contained = Contains(location); + if (is_contained) + { + return 0.; + } + + enum Direction + { + INVALID = 0, + NORTH = 1, + SOUTH = 2, + EAST = 4, + NORTH_EAST = 5, + SOUTH_EAST = 6, + WEST = 8, + NORTH_WEST = 9, + SOUTH_WEST = 10 + }; + + Direction d = INVALID; + if (location.lat > max_lat) + d = (Direction) (d | NORTH); + else if (location.lat < min_lat) + d = (Direction) (d | SOUTH); + if (location.lon > max_lon) + d = (Direction) (d | EAST); + else if (location.lon < min_lon) + d = (Direction) (d | WEST); + + BOOST_ASSERT(d != INVALID); + + float min_dist = std::numeric_limits::max(); + switch (d) + { + case NORTH: + min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, location.lon)); + break; + case SOUTH: + min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, location.lon)); + break; + case WEST: + min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, min_lon)); + break; + case EAST: + min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, max_lon)); + break; + case NORTH_EAST: + min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, max_lon)); + break; + case NORTH_WEST: + min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, min_lon)); + break; + case SOUTH_EAST: + min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, max_lon)); + break; + case SOUTH_WEST: + min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, min_lon)); + break; + default: + break; + } + + BOOST_ASSERT(min_dist != std::numeric_limits::max()); + + return min_dist; + } + + inline float GetMinMaxDist(const FixedPointCoordinate &location) const + { + float min_max_dist = std::numeric_limits::max(); + // Get minmax distance to each of the four sides + const FixedPointCoordinate upper_left(max_lat, min_lon); + const FixedPointCoordinate upper_right(max_lat, max_lon); + const FixedPointCoordinate lower_right(min_lat, max_lon); + const FixedPointCoordinate lower_left(min_lat, min_lon); + + min_max_dist = std::min( + min_max_dist, + std::max( + FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left), + FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right))); + + min_max_dist = std::min( + min_max_dist, + std::max( + FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right), + FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right))); + + min_max_dist = std::min( + min_max_dist, + std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right), + FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left))); + + min_max_dist = std::min( + min_max_dist, + std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left), + FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left))); + return min_max_dist; + } + + inline bool Contains(const FixedPointCoordinate &location) const + { + const bool lats_contained = (location.lat >= min_lat) && (location.lat <= max_lat); + const bool lons_contained = (location.lon >= min_lon) && (location.lon <= max_lon); + return lats_contained && lons_contained; + } + + inline friend std::ostream &operator<<(std::ostream &out, const RectangleInt2D &rect) + { + out << rect.min_lat / COORDINATE_PRECISION << "," << rect.min_lon / COORDINATE_PRECISION + << " " << rect.max_lat / COORDINATE_PRECISION << "," + << rect.max_lon / COORDINATE_PRECISION; + return out; + } + }; + using RectangleT = RectangleInt2D; struct TreeNode @@ -229,7 +412,7 @@ class StaticRTree } // generate tree node that resemble the objects in leaf and store it for next level - InitializeMBRectangle(current_node.minimum_bounding_rectangle, + current_node.minimum_bounding_rectangle.InitializeMBRectangle( current_leaf.objects, current_leaf.object_count, coordinate_list); current_node.child_is_on_disk = true; current_node.children[0] = tree_nodes_in_level.size(); @@ -1016,33 +1199,6 @@ class StaticRTree { return (a == b && c == d) || (a == c && b == d) || (a == d && b == c); } - - inline void InitializeMBRectangle(RectangleT& rectangle, - const std::array &objects, - const uint32_t element_count, - const std::vector &coordinate_list) - { - for (uint32_t i = 0; i < element_count; ++i) - { - rectangle.min_lon = std::min(rectangle.min_lon, - std::min(coordinate_list.at(objects[i].u).lon, - coordinate_list.at(objects[i].v).lon)); - rectangle.max_lon = std::max(rectangle.max_lon, - std::max(coordinate_list.at(objects[i].u).lon, - coordinate_list.at(objects[i].v).lon)); - - rectangle.min_lat = std::min(rectangle.min_lat, - std::min(coordinate_list.at(objects[i].u).lat, - coordinate_list.at(objects[i].v).lat)); - rectangle.max_lat = std::max(rectangle.max_lat, - std::max(coordinate_list.at(objects[i].u).lat, - coordinate_list.at(objects[i].v).lat)); - } - BOOST_ASSERT(rectangle.min_lat != std::numeric_limits::min()); - BOOST_ASSERT(rectangle.min_lon != std::numeric_limits::min()); - BOOST_ASSERT(rectangle.max_lat != std::numeric_limits::min()); - BOOST_ASSERT(rectangle.max_lon != std::numeric_limits::min()); - } }; //[1] "On Packing R-Trees"; I. Kamel, C. Faloutsos; 1993; DOI: 10.1145/170088.170403 diff --git a/Descriptors/DescriptionFactory.h b/Descriptors/DescriptionFactory.h index 7eb4661ca35..ac4c70234ff 100644 --- a/Descriptors/DescriptionFactory.h +++ b/Descriptors/DescriptionFactory.h @@ -190,7 +190,7 @@ class DescriptionFactory } // Generalize poly line - polyline_generalizer.Run(path_description.begin(), path_description.end(), zoomLevel); + polyline_generalizer.Run(path_description, zoomLevel); // fix what needs to be fixed else unsigned necessary_pieces = 0; // a running index that counts the necessary pieces diff --git a/Util/TimingUtil.h b/Util/TimingUtil.h index 5f16ff7ca47..c1505cebfe7 100644 --- a/Util/TimingUtil.h +++ b/Util/TimingUtil.h @@ -28,53 +28,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef TIMINGUTIL_H #define TIMINGUTIL_H -#include #include -#include -#include -#include - -struct GlobalTimer -{ - GlobalTimer() : time(0) {} - std::atomic time; -}; - -class GlobalTimerFactory -{ -public: - static GlobalTimerFactory& get() - { - static GlobalTimerFactory instance; - return instance; - } - - GlobalTimer& getGlobalTimer(const std::string& name) - { - std::lock_guard lock(map_mutex); - return timer_map[name]; - } - -private: - std::mutex map_mutex; - std::unordered_map timer_map; -}; - -#define GLOBAL_TIMER_AQUIRE(_X) auto& _X##_global_timer = GlobalTimerFactory::get().getGlobalTimer(#_X) -#define GLOBAL_TIMER_RESET(_X) _X##_global_timer.time = 0 -#define GLOBAL_TIMER_START(_X) TIMER_START(_X) -#define GLOBAL_TIMER_STOP(_X) TIMER_STOP(_X); _X##_global_timer.time += TIMER_NSEC(_X) -#define GLOBAL_TIMER_NSEC(_X) static_cast(_X##_global_timer.time) -#define GLOBAL_TIMER_USEC(_X) (_X##_global_timer.time / 1000.0) -#define GLOBAL_TIMER_MSEC(_X) (_X##_global_timer.time / 1000.0 / 1000.0) -#define GLOBAL_TIMER_SEC(_X) (_X##_global_timer.time / 1000.0 / 1000.0 / 1000.0) #define TIMER_START(_X) auto _X##_start = std::chrono::steady_clock::now(), _X##_stop = _X##_start #define TIMER_STOP(_X) _X##_stop = std::chrono::steady_clock::now() -#define TIMER_NSEC(_X) std::chrono::duration_cast(_X##_stop - _X##_start).count() -#define TIMER_USEC(_X) std::chrono::duration_cast(_X##_stop - _X##_start).count() -#define TIMER_MSEC(_X) (0.000001*std::chrono::duration_cast(_X##_stop - _X##_start).count()) -#define TIMER_SEC(_X) (0.000001*std::chrono::duration_cast(_X##_stop - _X##_start).count()) +#define TIMER_MSEC(_X) std::chrono::duration_cast(_X##_stop - _X##_start).count() +#define TIMER_SEC(_X) (0.001*std::chrono::duration_cast(_X##_stop - _X##_start).count()) #define TIMER_MIN(_X) std::chrono::duration_cast(_X##_stop - _X##_start).count() #endif // TIMINGUTIL_H diff --git a/Util/TrigonometryTables.h b/Util/TrigonometryTables.h index d14540482d2..64076a23c35 100644 --- a/Util/TrigonometryTables.h +++ b/Util/TrigonometryTables.h @@ -722,7 +722,7 @@ constexpr unsigned short atan_table[4096] = { // max value is pi/4 constexpr double SCALING_FACTOR = 4. / M_PI * 0xFFFF; -inline double atan2_lookup(double y, double x) +double atan2_lookup(double y, double x) { if (std::abs(x) < std::numeric_limits::epsilon()) {