Merge branch 'revert-1240-revert-1217-sketch-upstream' into develop
This commit is contained in:
		
						commit
						8700007025
					
				| @ -83,62 +83,40 @@ struct CoordinatePairCalculator | ||||
| }; | ||||
| } | ||||
| 
 | ||||
| DouglasPeucker::DouglasPeucker() | ||||
|     : douglas_peucker_thresholds({ | ||||
|           512440, // z0
 | ||||
|           256720, // z1
 | ||||
|           122560, // z2
 | ||||
|           56780,  // z3
 | ||||
|           28800,  // z4
 | ||||
|           14400,  // z5
 | ||||
|           7200,   // z6
 | ||||
|           3200,   // z7
 | ||||
|           2400,   // z8
 | ||||
|           1000,   // z9
 | ||||
|           600,    // z10
 | ||||
|           120,    // z11
 | ||||
|           60,     // z12
 | ||||
|           45,     // z13
 | ||||
|           36,     // z14
 | ||||
|           20,     // z15
 | ||||
|           8,      // z16
 | ||||
|           6,      // z17
 | ||||
|           4       // z18
 | ||||
|       }) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level) | ||||
| { | ||||
|     // check if input data is invalid
 | ||||
|     BOOST_ASSERT_MSG(!input_geometry.empty(), "geometry invalid"); | ||||
|     Run(std::begin(input_geometry), std::end(input_geometry), zoom_level); | ||||
| } | ||||
| 
 | ||||
|     if (input_geometry.size() < 2) | ||||
| void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level) | ||||
| { | ||||
|     unsigned size = std::distance(begin, end); | ||||
|     if (size < 2) | ||||
|     { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     input_geometry.front().necessary = true; | ||||
|     input_geometry.back().necessary = true; | ||||
|     begin->necessary = true; | ||||
|     std::prev(end)->necessary = true; | ||||
| 
 | ||||
|     { | ||||
|         BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level"); | ||||
|         unsigned left_border = 0; | ||||
|         unsigned right_border = 1; | ||||
|         RandomAccessIt left_border = begin; | ||||
|         RandomAccessIt right_border = std::next(begin); | ||||
|         // Sweep over array and identify those ranges that need to be checked
 | ||||
|         do | ||||
|         { | ||||
|             // traverse list until new border element found
 | ||||
|             if (input_geometry[right_border].necessary) | ||||
|             if (right_border->necessary) | ||||
|             { | ||||
|                 // sanity checks
 | ||||
|                 BOOST_ASSERT(input_geometry[left_border].necessary); | ||||
|                 BOOST_ASSERT(input_geometry[right_border].necessary); | ||||
|                 BOOST_ASSERT(left_border->necessary); | ||||
|                 BOOST_ASSERT(right_border->necessary); | ||||
|                 recursion_stack.emplace(left_border, right_border); | ||||
|                 left_border = right_border; | ||||
|             } | ||||
|             ++right_border; | ||||
|         } while (right_border < input_geometry.size()); | ||||
|         } while (right_border != end); | ||||
|     } | ||||
| 
 | ||||
|     // mark locations as 'necessary' by divide-and-conquer
 | ||||
| @ -148,40 +126,40 @@ void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const | ||||
|         const GeometryRange pair = recursion_stack.top(); | ||||
|         recursion_stack.pop(); | ||||
|         // sanity checks
 | ||||
|         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"); | ||||
|         BOOST_ASSERT_MSG(pair.first->necessary, "left border must 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"); | ||||
| 
 | ||||
|         int max_int_distance = 0; | ||||
|         unsigned farthest_entry_index = pair.second; | ||||
|         const CoordinatePairCalculator dist_calc(input_geometry[pair.first].location, | ||||
|                                                  input_geometry[pair.second].location); | ||||
|         auto farthest_entry_it = pair.second; | ||||
|         const CoordinatePairCalculator dist_calc(pair.first->location, pair.second->location); | ||||
| 
 | ||||
|         // sweep over range to find the maximum
 | ||||
|         for (const auto i : osrm::irange(pair.first + 1, pair.second)) | ||||
|         for (auto it = std::next(pair.first); it != pair.second; ++it) | ||||
|         { | ||||
|             const int distance = dist_calc(input_geometry[i].location); | ||||
|             const int distance = dist_calc(it->location); | ||||
|             // found new feasible maximum?
 | ||||
|             if (distance > max_int_distance && distance > douglas_peucker_thresholds[zoom_level]) | ||||
|             if (distance > max_int_distance && distance > DOUGLAS_PEUCKER_THRESHOLDS[zoom_level]) | ||||
|             { | ||||
|                 farthest_entry_index = i; | ||||
|                 farthest_entry_it = it; | ||||
|                 max_int_distance = distance; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         // check if maximum violates a zoom level dependent threshold
 | ||||
|         if (max_int_distance > douglas_peucker_thresholds[zoom_level]) | ||||
|         if (max_int_distance > DOUGLAS_PEUCKER_THRESHOLDS[zoom_level]) | ||||
|         { | ||||
|             //  mark idx as necessary
 | ||||
|             input_geometry[farthest_entry_index].necessary = true; | ||||
|             if (1 < (farthest_entry_index - pair.first)) | ||||
|             farthest_entry_it->necessary = true; | ||||
|             if (1 < std::distance(pair.first, farthest_entry_it)) | ||||
|             { | ||||
|                 recursion_stack.emplace(pair.first, farthest_entry_index); | ||||
|                 recursion_stack.emplace(pair.first, farthest_entry_it); | ||||
|             } | ||||
|             if (1 < (pair.second - farthest_entry_index)) | ||||
|             if (1 < std::distance(farthest_entry_it, pair.second)) | ||||
|             { | ||||
|                 recursion_stack.emplace(farthest_entry_index, pair.second); | ||||
|                 recursion_stack.emplace(farthest_entry_it, pair.second); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| #include <stack> | ||||
| #include <utility> | ||||
| #include <vector> | ||||
| #include <array> | ||||
| 
 | ||||
| /* This class object computes the bitvector of indicating generalized input
 | ||||
|  * points according to the (Ramer-)Douglas-Peucker algorithm. | ||||
| @ -40,18 +41,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  * Note: points may also be pre-selected*/ | ||||
| 
 | ||||
| struct SegmentInformation; | ||||
| static const std::array<int, 19> DOUGLAS_PEUCKER_THRESHOLDS = { | ||||
|                                   512440, // z0
 | ||||
|                                   256720, // z1
 | ||||
|                                   122560, // z2
 | ||||
|                                   56780,  // z3
 | ||||
|                                   28800,  // z4
 | ||||
|                                   14400,  // z5
 | ||||
|                                   7200,   // z6
 | ||||
|                                   3200,   // z7
 | ||||
|                                   2400,   // z8
 | ||||
|                                   1000,   // z9
 | ||||
|                                   600,    // z10
 | ||||
|                                   120,    // z11
 | ||||
|                                   60,     // z12
 | ||||
|                                   45,     // z13
 | ||||
|                                   36,     // z14
 | ||||
|                                   20,     // z15
 | ||||
|                                   8,      // z16
 | ||||
|                                   6,      // z17
 | ||||
|                                   4       // z18
 | ||||
| }; | ||||
| 
 | ||||
| class DouglasPeucker | ||||
| { | ||||
|   private: | ||||
|     std::vector<int> douglas_peucker_thresholds; | ||||
|   public: | ||||
|     using RandomAccessIt = std::vector<SegmentInformation>::iterator; | ||||
| 
 | ||||
|     using GeometryRange = std::pair<unsigned, unsigned>; | ||||
|     using GeometryRange = std::pair<RandomAccessIt, RandomAccessIt>; | ||||
|     // Stack to simulate the recursion
 | ||||
|     std::stack<GeometryRange> recursion_stack; | ||||
| 
 | ||||
|   public: | ||||
|     DouglasPeucker(); | ||||
|     void Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level); | ||||
|     void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level); | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -41,7 +41,7 @@ add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp FingerPrint.c | ||||
|   VERBATIM) | ||||
| 
 | ||||
| add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp) | ||||
| add_custom_target(tests DEPENDS datastructure-tests) | ||||
| add_custom_target(tests DEPENDS datastructure-tests algorithm-tests) | ||||
| add_custom_target(benchmarks DEPENDS rtree-bench) | ||||
| 
 | ||||
| set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread unit_test_framework) | ||||
| @ -72,6 +72,7 @@ file(GLOB AlgorithmGlob Algorithms/*.cpp) | ||||
| file(GLOB HttpGlob Server/Http/*.cpp) | ||||
| file(GLOB LibOSRMGlob Library/*.cpp) | ||||
| file(GLOB DataStructureTestsGlob UnitTests/DataStructures/*.cpp DataStructures/HilbertValue.cpp) | ||||
| file(GLOB AlgorithmTestsGlob UnitTests/Algorithms/*.cpp) | ||||
| 
 | ||||
| set( | ||||
|   OSRMSources | ||||
| @ -93,6 +94,7 @@ add_executable(osrm-datastore datastore.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGE | ||||
| 
 | ||||
| # Unit tests | ||||
| add_executable(datastructure-tests EXCLUDE_FROM_ALL UnitTests/datastructure_tests.cpp ${DataStructureTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE>) | ||||
| add_executable(algorithm-tests EXCLUDE_FROM_ALL UnitTests/algorithm_tests.cpp ${AlgorithmTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE>) | ||||
| 
 | ||||
| # Benchmarks | ||||
| add_executable(rtree-bench EXCLUDE_FROM_ALL Benchmarks/StaticRTreeBench.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE>) | ||||
| @ -195,6 +197,7 @@ target_link_libraries(osrm-prepare ${Boost_LIBRARIES}) | ||||
| target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM) | ||||
| target_link_libraries(osrm-datastore ${Boost_LIBRARIES}) | ||||
| target_link_libraries(datastructure-tests ${Boost_LIBRARIES}) | ||||
| target_link_libraries(algorithm-tests ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM) | ||||
| target_link_libraries(rtree-bench ${Boost_LIBRARIES}) | ||||
| 
 | ||||
| find_package(Threads REQUIRED) | ||||
| @ -203,6 +206,7 @@ target_link_libraries(osrm-datastore ${CMAKE_THREAD_LIBS_INIT}) | ||||
| target_link_libraries(osrm-prepare ${CMAKE_THREAD_LIBS_INIT}) | ||||
| target_link_libraries(OSRM ${CMAKE_THREAD_LIBS_INIT}) | ||||
| target_link_libraries(datastructure-tests ${CMAKE_THREAD_LIBS_INIT}) | ||||
| target_link_libraries(algorithm-tests ${CMAKE_THREAD_LIBS_INIT}) | ||||
| target_link_libraries(rtree-bench ${CMAKE_THREAD_LIBS_INIT}) | ||||
| 
 | ||||
| find_package(TBB REQUIRED) | ||||
| @ -214,6 +218,7 @@ target_link_libraries(osrm-extract ${TBB_LIBRARIES}) | ||||
| target_link_libraries(osrm-prepare ${TBB_LIBRARIES}) | ||||
| target_link_libraries(osrm-routed ${TBB_LIBRARIES}) | ||||
| target_link_libraries(datastructure-tests ${TBB_LIBRARIES}) | ||||
| target_link_libraries(algorithm-tests ${TBB_LIBRARIES}) | ||||
| target_link_libraries(rtree-bench ${TBB_LIBRARIES}) | ||||
| include_directories(${TBB_INCLUDE_DIR}) | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										172
									
								
								DataStructures/Rectangle.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								DataStructures/Rectangle.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,172 @@ | ||||
| #ifndef RECTANGLE_H | ||||
| #define RECTANGLE_H | ||||
| 
 | ||||
| #include <boost/assert.hpp> | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <cstdint> | ||||
| #include <limits> | ||||
| 
 | ||||
| // TODO: Make template type, add tests
 | ||||
| struct RectangleInt2D | ||||
| { | ||||
|     RectangleInt2D() : min_lon(std::numeric_limits<int32_t>::max()), | ||||
|                        max_lon(std::numeric_limits<int32_t>::min()), | ||||
|                        min_lat(std::numeric_limits<int32_t>::max()), | ||||
|                        max_lat(std::numeric_limits<int32_t>::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<int32_t>::min()); | ||||
|         BOOST_ASSERT(min_lon != std::numeric_limits<int32_t>::min()); | ||||
|         BOOST_ASSERT(max_lat != std::numeric_limits<int32_t>::min()); | ||||
|         BOOST_ASSERT(max_lon != std::numeric_limits<int32_t>::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<float>::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<float>::max()); | ||||
| 
 | ||||
|         return min_dist; | ||||
|     } | ||||
| 
 | ||||
|     inline float GetMinMaxDist(const FixedPointCoordinate &location) const | ||||
|     { | ||||
|         float min_max_dist = std::numeric_limits<float>::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 | ||||
| @ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| #include "HilbertValue.h" | ||||
| #include "phantom_node.hpp" | ||||
| #include "QueryNode.h" | ||||
| #include "Rectangle.h" | ||||
| #include "SharedMemoryFactory.h" | ||||
| #include "SharedMemoryVectorWrapper.h" | ||||
| 
 | ||||
| @ -70,190 +71,6 @@ template <class EdgeDataT, | ||||
| class StaticRTree | ||||
| { | ||||
|   public: | ||||
|     struct RectangleInt2D | ||||
|     { | ||||
|         RectangleInt2D() : min_lon(INT_MAX), max_lon(INT_MIN), min_lat(INT_MAX), max_lat(INT_MIN) {} | ||||
| 
 | ||||
|         int32_t min_lon, max_lon; | ||||
|         int32_t min_lat, max_lat; | ||||
| 
 | ||||
|         inline void InitializeMBRectangle(const std::array<EdgeDataT, LEAF_NODE_SIZE> &objects, | ||||
|                                           const uint32_t element_count, | ||||
|                                           const std::vector<NodeInfo> &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<int>::min()); | ||||
|             BOOST_ASSERT(min_lon != std::numeric_limits<int>::min()); | ||||
|             BOOST_ASSERT(max_lat != std::numeric_limits<int>::min()); | ||||
|             BOOST_ASSERT(max_lon != std::numeric_limits<int>::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<int>::min()); | ||||
|             BOOST_ASSERT(min_lon != std::numeric_limits<int>::min()); | ||||
|             BOOST_ASSERT(max_lat != std::numeric_limits<int>::min()); | ||||
|             BOOST_ASSERT(max_lon != std::numeric_limits<int>::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<float>::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<float>::max()); | ||||
| 
 | ||||
|             return min_dist; | ||||
|         } | ||||
| 
 | ||||
|         inline float GetMinMaxDist(const FixedPointCoordinate &location) const | ||||
|         { | ||||
|             float min_max_dist = std::numeric_limits<float>::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 | ||||
| @ -412,7 +229,7 @@ class StaticRTree | ||||
|             } | ||||
| 
 | ||||
|             // generate tree node that resemble the objects in leaf and store it for next level
 | ||||
|             current_node.minimum_bounding_rectangle.InitializeMBRectangle( | ||||
|             InitializeMBRectangle(current_node.minimum_bounding_rectangle, | ||||
|                 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(); | ||||
| @ -1199,6 +1016,33 @@ class StaticRTree | ||||
|     { | ||||
|         return (a == b && c == d) || (a == c && b == d) || (a == d && b == c); | ||||
|     } | ||||
| 
 | ||||
|     inline void InitializeMBRectangle(RectangleT& rectangle, | ||||
|                                       const std::array<EdgeDataT, LEAF_NODE_SIZE> &objects, | ||||
|                                       const uint32_t element_count, | ||||
|                                       const std::vector<NodeInfo> &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<int>::min()); | ||||
|         BOOST_ASSERT(rectangle.min_lon != std::numeric_limits<int>::min()); | ||||
|         BOOST_ASSERT(rectangle.max_lat != std::numeric_limits<int>::min()); | ||||
|         BOOST_ASSERT(rectangle.max_lon != std::numeric_limits<int>::min()); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| //[1] "On Packing R-Trees"; I. Kamel, C. Faloutsos; 1993; DOI: 10.1145/170088.170403
 | ||||
|  | ||||
| @ -194,7 +194,7 @@ class DescriptionFactory | ||||
|         } | ||||
| 
 | ||||
|         // Generalize poly line
 | ||||
|         polyline_generalizer.Run(path_description, zoomLevel); | ||||
|         polyline_generalizer.Run(path_description.begin(), path_description.end(), zoomLevel); | ||||
| 
 | ||||
|         // fix what needs to be fixed else
 | ||||
|         unsigned necessary_pieces = 0; // a running index that counts the necessary pieces
 | ||||
|  | ||||
							
								
								
									
										83
									
								
								UnitTests/Algorithms/DouglasPeuckerTest.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								UnitTests/Algorithms/DouglasPeuckerTest.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,83 @@ | ||||
| #include "../../Algorithms/DouglasPeucker.h" | ||||
| #include "../../DataStructures/SegmentInformation.h" | ||||
| #include "../../Include/osrm/Coordinate.h" | ||||
| 
 | ||||
| #include <boost/test/unit_test.hpp> | ||||
| #include <boost/test/test_case_template.hpp> | ||||
| #include <boost/mpl/list.hpp> | ||||
| 
 | ||||
| #include <iostream> | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE(douglas_peucker) | ||||
| 
 | ||||
| SegmentInformation getTestInfo(int lat, int lon, bool necessary) | ||||
| { | ||||
|     return SegmentInformation(FixedPointCoordinate(lat, lon), | ||||
|                               0, 0, 0, TurnInstruction::HeadOn, necessary, false, 0); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(all_necessary_test) | ||||
| { | ||||
|     /*
 | ||||
|      *     x | ||||
|      *    / \ | ||||
|      *   x   \ | ||||
|      *  /     \ | ||||
|      * x       x | ||||
|      */ | ||||
|     std::vector<SegmentInformation> info = { | ||||
|         getTestInfo(5, 5, true), | ||||
|         getTestInfo(6, 6, true), | ||||
|         getTestInfo(10, 10, true), | ||||
|         getTestInfo(5, 15, true) | ||||
|     }; | ||||
|     DouglasPeucker dp; | ||||
|     for (unsigned z = 0; z < 20; z++) | ||||
|     { | ||||
|         dp.Run(info, z); | ||||
|         for (const auto& i : info) | ||||
|         { | ||||
|             BOOST_CHECK_EQUAL(i.necessary, true); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(remove_second_node_test) | ||||
| { | ||||
|     DouglasPeucker dp; | ||||
|     for (unsigned z = 0; z < 19; z++) | ||||
|     { | ||||
|         /*
 | ||||
|          *   x--x | ||||
|          *   |   \ | ||||
|          * x-x    x | ||||
|          *        | | ||||
|          *        x | ||||
|          */ | ||||
|         std::vector<SegmentInformation> info = { | ||||
|             getTestInfo(5  * COORDINATE_PRECISION, | ||||
|                         5  * COORDINATE_PRECISION, true), | ||||
|             getTestInfo(5  * COORDINATE_PRECISION, | ||||
|                         5  * COORDINATE_PRECISION + DOUGLAS_PEUCKER_THRESHOLDS[z], false), | ||||
|             getTestInfo(10 * COORDINATE_PRECISION, | ||||
|                         10 * COORDINATE_PRECISION, false), | ||||
|             getTestInfo(10 * COORDINATE_PRECISION, | ||||
|                         10 + COORDINATE_PRECISION + DOUGLAS_PEUCKER_THRESHOLDS[z] * 2, false), | ||||
|             getTestInfo(5  * COORDINATE_PRECISION, | ||||
|                         15 * COORDINATE_PRECISION, false), | ||||
|             getTestInfo(5  * COORDINATE_PRECISION + DOUGLAS_PEUCKER_THRESHOLDS[z], | ||||
|                         15 * COORDINATE_PRECISION, true), | ||||
|         }; | ||||
|         std::cout << "Threshold: " << DOUGLAS_PEUCKER_THRESHOLDS[z] << std::endl; | ||||
|         dp.Run(info, z); | ||||
|         std::cout << "z: " << z << std::endl; | ||||
|         BOOST_CHECK_EQUAL(info[0].necessary, true); | ||||
|         BOOST_CHECK_EQUAL(info[1].necessary, false); | ||||
|         BOOST_CHECK_EQUAL(info[2].necessary, true); | ||||
|         BOOST_CHECK_EQUAL(info[3].necessary, true); | ||||
|         BOOST_CHECK_EQUAL(info[4].necessary, false); | ||||
|         BOOST_CHECK_EQUAL(info[5].necessary, true); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE_END() | ||||
							
								
								
									
										8
									
								
								UnitTests/algorithm_tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								UnitTests/algorithm_tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| #define BOOST_TEST_MODULE algorithm tests | ||||
| 
 | ||||
| #include <boost/test/unit_test.hpp> | ||||
| 
 | ||||
| /*
 | ||||
|  * This file will contain an automatically generated main function. | ||||
|  */ | ||||
| 
 | ||||
| @ -28,12 +28,53 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| #ifndef TIMINGUTIL_H | ||||
| #define TIMINGUTIL_H | ||||
| 
 | ||||
| #include <atomic> | ||||
| #include <chrono> | ||||
| #include <cstdint> | ||||
| #include <mutex> | ||||
| #include <unordered_map> | ||||
| 
 | ||||
| struct GlobalTimer | ||||
| { | ||||
|     GlobalTimer() : time(0) {} | ||||
|     std::atomic<uint64_t> time; | ||||
| }; | ||||
| 
 | ||||
| class GlobalTimerFactory | ||||
| { | ||||
| public: | ||||
|     static GlobalTimerFactory& get() | ||||
|     { | ||||
|         static GlobalTimerFactory instance; | ||||
|         return instance; | ||||
|     } | ||||
| 
 | ||||
|     GlobalTimer& getGlobalTimer(const std::string& name) | ||||
|     { | ||||
|         std::lock_guard<std::mutex> lock(map_mutex); | ||||
|         return timer_map[name]; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     std::mutex map_mutex; | ||||
|     std::unordered_map<std::string, GlobalTimer> 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<double>(_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_MSEC(_X) std::chrono::duration_cast<std::chrono::milliseconds>(_X##_stop - _X##_start).count() | ||||
| #define TIMER_SEC(_X) (0.001*std::chrono::duration_cast<std::chrono::milliseconds>(_X##_stop - _X##_start).count()) | ||||
| #define TIMER_NSEC(_X) std::chrono::duration_cast<std::chrono::nanoseconds>(_X##_stop - _X##_start).count() | ||||
| #define TIMER_USEC(_X) std::chrono::duration_cast<std::chrono::microseconds>(_X##_stop - _X##_start).count() | ||||
| #define TIMER_MSEC(_X) (0.000001*std::chrono::duration_cast<std::chrono::nanoseconds>(_X##_stop - _X##_start).count()) | ||||
| #define TIMER_SEC(_X)  (0.000001*std::chrono::duration_cast<std::chrono::microseconds>(_X##_stop - _X##_start).count()) | ||||
| #define TIMER_MIN(_X) std::chrono::duration_cast<std::chrono::minutes>(_X##_stop - _X##_start).count() | ||||
| 
 | ||||
| #endif // TIMINGUTIL_H
 | ||||
|  | ||||
| @ -722,7 +722,7 @@ constexpr unsigned short atan_table[4096] = { | ||||
| // max value is pi/4
 | ||||
| constexpr double SCALING_FACTOR = 4. / M_PI * 0xFFFF; | ||||
| 
 | ||||
| double atan2_lookup(double y, double x) | ||||
| inline double atan2_lookup(double y, double x) | ||||
| { | ||||
|     if (std::abs(x) < std::numeric_limits<double>::epsilon()) | ||||
|     { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user