From 5841dd3b83ac88fd107b8662a044fc0726246ee0 Mon Sep 17 00:00:00 2001 From: mapsam Date: Wed, 22 Nov 2017 08:49:43 -0800 Subject: [PATCH 1/2] operator for empty geometry types --- include/mapbox/geometry/algorithms/closest_point_impl.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/mapbox/geometry/algorithms/closest_point_impl.hpp b/include/mapbox/geometry/algorithms/closest_point_impl.hpp index 4f92743..cd8a5d7 100644 --- a/include/mapbox/geometry/algorithms/closest_point_impl.hpp +++ b/include/mapbox/geometry/algorithms/closest_point_impl.hpp @@ -16,6 +16,10 @@ struct closest_point closest_point(mapbox::geometry::point const& pt) : pt_(pt) {} + result_type operator() (mapbox::geometry::empty) const { + return result_type(); + } + result_type operator() (mapbox::geometry::point const& pt) const { info_type info; From 03a0d4971521b542316a8918ba1bada731158520 Mon Sep 17 00:00:00 2001 From: Blake Thompson Date: Wed, 22 Nov 2017 15:14:09 -0600 Subject: [PATCH 2/2] Added support for closet point with empty geometries --- CMakeLists.txt | 2 +- .../geometry/algorithms/closest_point.hpp | 1 + .../algorithms/closest_point_impl.hpp | 12 +- src/closest_point_d.cpp | 1 + src/closest_point_i64.cpp | 1 + .../unit/closest_point/test-closest-point.cpp | 134 +++++++++++++++++- 6 files changed, 144 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8196d39..515b120 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ include(cmake/spatialalgorithms.cmake) include(cmake/mason.cmake) mason_use(boost VERSION 1.63.0 HEADER_ONLY) -mason_use(geometry VERSION 0.9.0 HEADER_ONLY) +mason_use(geometry VERSION 96d3505 HEADER_ONLY) mason_use(variant VERSION 1.1.4 HEADER_ONLY) mason_use(wagyu VERSION 0.4.1 HEADER_ONLY) diff --git a/include/mapbox/geometry/algorithms/closest_point.hpp b/include/mapbox/geometry/algorithms/closest_point.hpp index 5c252f9..4f5fc59 100644 --- a/include/mapbox/geometry/algorithms/closest_point.hpp +++ b/include/mapbox/geometry/algorithms/closest_point.hpp @@ -17,4 +17,5 @@ struct closest_point_info template closest_point_info closest_point(T1 const& geom, mapbox::geometry::point const& pt); + }}} diff --git a/include/mapbox/geometry/algorithms/closest_point_impl.hpp b/include/mapbox/geometry/algorithms/closest_point_impl.hpp index cd8a5d7..3e2ed3e 100644 --- a/include/mapbox/geometry/algorithms/closest_point_impl.hpp +++ b/include/mapbox/geometry/algorithms/closest_point_impl.hpp @@ -74,17 +74,19 @@ struct closest_point { if (first) { - first = false; result = std::move(operator()(geom)); - if (boost::geometry::math::equals(result.distance, 0.0)) - { - return result; + if (!(result.distance < 0.0)) { + first = false; + if (boost::geometry::math::equals(result.distance, 0.0)) + { + return result; + } } } else { auto sub_result = operator()(geom); - if (sub_result.distance < result.distance) + if (sub_result.distance < result.distance && !(sub_result.distance < 0.0)) { result = std::move(sub_result); } diff --git a/src/closest_point_d.cpp b/src/closest_point_d.cpp index 8c5272a..735e11c 100644 --- a/src/closest_point_d.cpp +++ b/src/closest_point_d.cpp @@ -4,6 +4,7 @@ namespace mapbox { namespace geometry { namespace algorithms { +template closest_point_info closest_point(empty const&, point const&); template closest_point_info closest_point(geometry const&, point const&); template closest_point_info closest_point(point const&, point const&); template closest_point_info closest_point(line_string const&, point const&); diff --git a/src/closest_point_i64.cpp b/src/closest_point_i64.cpp index 2fe5e5a..7fde572 100644 --- a/src/closest_point_i64.cpp +++ b/src/closest_point_i64.cpp @@ -4,6 +4,7 @@ namespace mapbox { namespace geometry { namespace algorithms { +template closest_point_info closest_point(empty const&, point const&); template closest_point_info closest_point(geometry const&, point const&); template closest_point_info closest_point(point const&, point const&); template closest_point_info closest_point(line_string const&, point const&); diff --git a/test/unit/closest_point/test-closest-point.cpp b/test/unit/closest_point/test-closest-point.cpp index 6657d81..beb64a6 100644 --- a/test/unit/closest_point/test-closest-point.cpp +++ b/test/unit/closest_point/test-closest-point.cpp @@ -10,6 +10,25 @@ void test_closest_point_d() { using namespace mapbox::geometry; namespace op = algorithms; + // Point => Empty + { + empty e; + point p1{0.0, 0.0}; + point p2{3.0, 4.0}; + { + auto result = op::closest_point(e, p2); + BOOST_CHECK_CLOSE(result.x, 0.0, 1e-06); + BOOST_CHECK_CLOSE(result.y, 0.0, 1e-06); + BOOST_CHECK_CLOSE(result.distance, -1.0, 1e-06); + } + { + auto result = op::closest_point(e, p1); + BOOST_CHECK_CLOSE(result.x, 0.0, 1e-06); + BOOST_CHECK_CLOSE(result.y, 0.0, 1e-06); + BOOST_CHECK_CLOSE(result.distance, -1.0, 1e-06); + } + } + // Point => Point { point p1{0.0, 0.0}; @@ -112,12 +131,78 @@ void test_closest_point_d() BOOST_CHECK_CLOSE(result.y, 3.0, 1e-06); BOOST_CHECK_CLOSE(result.distance, std::sqrt(5.0), 1e-03); } + + // Point => Geometry + { + multi_polygon mpoly { + {{{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}}}, + {{{2, 2}, {3, 2}, {3, 3}, {2, 3}, {2, 2}}} + }; + geometry geom(std::move(mpoly)); + point pt {4.0, 5.0}; + auto result = op::closest_point(geom, pt); + BOOST_CHECK_CLOSE(result.x, 3.0, 1e-06); + BOOST_CHECK_CLOSE(result.y, 3.0, 1e-06); + BOOST_CHECK_CLOSE(result.distance, std::sqrt(5.0), 1e-03); + } + + // Point => Geometry Collection + { + multi_polygon mpoly { + {{{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}}}, + {{{2, 2}, {3, 2}, {3, 3}, {2, 3}, {2, 2}}} + }; + geometry geom1(std::move(mpoly)); + geometry geom2; // empty geometry + multi_point mp{{-1,-1}, {1, 1}}; + geometry geom3(std::move(mp)); + + geometry_collection gc; + gc.push_back(geom1); + gc.push_back(geom2); + gc.push_back(geom3); + + point pt {4, 5}; + auto result = op::closest_point(gc, pt); + BOOST_CHECK_CLOSE(result.x, 3.0, 1e-06); + BOOST_CHECK_CLOSE(result.y, 3.0, 1e-06); + BOOST_CHECK_CLOSE(result.distance, std::sqrt(5.0), 1e-03); + + geometry_collection gc2; + gc2.push_back(geom2); // First is a empty geometry + gc2.push_back(geom1); + gc2.push_back(geom3); + + auto result2 = op::closest_point(gc2, pt); + BOOST_CHECK_CLOSE(result2.x, 3.0, 1e-06); + BOOST_CHECK_CLOSE(result2.y, 3.0, 1e-06); + BOOST_CHECK_CLOSE(result2.distance, std::sqrt(5.0), 1e-03); + } } void test_closest_point_int64() { using namespace mapbox::geometry; namespace op = algorithms; + // Point => Empty + { + empty e; + point p1{0, 0}; + point p2{3, 4}; + { + auto result = op::closest_point(e, p2); + BOOST_CHECK_CLOSE(result.x, 0.0, 1e-06); + BOOST_CHECK_CLOSE(result.y, 0.0, 1e-06); + BOOST_CHECK_CLOSE(result.distance, -1.0, 1e-06); + } + { + auto result = op::closest_point(e, p1); + BOOST_CHECK_CLOSE(result.x, 0.0, 1e-06); + BOOST_CHECK_CLOSE(result.y, 0.0, 1e-06); + BOOST_CHECK_CLOSE(result.distance, -1.0, 1e-06); + } + } + // Point => Point { point p1{0, 0}; @@ -207,7 +292,7 @@ void test_closest_point_int64() BOOST_CHECK_CLOSE(result.distance, 0.0, 1e-06); } } - // Point => MultiPolygon + // Point => MultiPolygon { multi_polygon mpoly { {{{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}}}, @@ -219,6 +304,53 @@ void test_closest_point_int64() BOOST_CHECK_CLOSE(result.y, 3.0, 1e-06); BOOST_CHECK_CLOSE(result.distance, std::sqrt(5.0), 1e-03); } + + // Point => Geometry + { + multi_polygon mpoly { + {{{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}}}, + {{{2, 2}, {3, 2}, {3, 3}, {2, 3}, {2, 2}}} + }; + geometry geom(std::move(mpoly)); + point pt {4, 5}; + auto result = op::closest_point(geom, pt); + BOOST_CHECK_CLOSE(result.x, 3.0, 1e-06); + BOOST_CHECK_CLOSE(result.y, 3.0, 1e-06); + BOOST_CHECK_CLOSE(result.distance, std::sqrt(5.0), 1e-03); + } + + // Point => Geometry Collection + { + multi_polygon mpoly { + {{{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}}}, + {{{2, 2}, {3, 2}, {3, 3}, {2, 3}, {2, 2}}} + }; + geometry geom1(std::move(mpoly)); + geometry geom2; // empty geometry + multi_point mp{{-1,-1}, {1, 1}}; + geometry geom3(std::move(mp)); + + geometry_collection gc; + gc.push_back(geom1); + gc.push_back(geom2); + gc.push_back(geom3); + + point pt {4, 5}; + auto result = op::closest_point(gc, pt); + BOOST_CHECK_CLOSE(result.x, 3.0, 1e-06); + BOOST_CHECK_CLOSE(result.y, 3.0, 1e-06); + BOOST_CHECK_CLOSE(result.distance, std::sqrt(5.0), 1e-03); + + geometry_collection gc2; + gc2.push_back(geom2); // First is a empty geometry + gc2.push_back(geom1); + gc2.push_back(geom3); + + auto result2 = op::closest_point(gc2, pt); + BOOST_CHECK_CLOSE(result2.x, 3.0, 1e-06); + BOOST_CHECK_CLOSE(result2.y, 3.0, 1e-06); + BOOST_CHECK_CLOSE(result2.distance, std::sqrt(5.0), 1e-03); + } } }// ns testing