From 3d4963f40c97d74c4c198e21f7ea012583dd732e Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Fri, 22 Sep 2017 13:21:50 +0200 Subject: [PATCH] move implementatio into *.cpp + return 'closest_point_result' struct. --- include/mapnik/geometry/closest_point.hpp | 107 +-------------- src/build.py | 1 + src/geometry/closest_point.cpp | 160 ++++++++++++++++++++++ 3 files changed, 168 insertions(+), 100 deletions(-) create mode 100644 src/geometry/closest_point.cpp diff --git a/include/mapnik/geometry/closest_point.hpp b/include/mapnik/geometry/closest_point.hpp index 4dd7a2989..47d704644 100644 --- a/include/mapnik/geometry/closest_point.hpp +++ b/include/mapnik/geometry/closest_point.hpp @@ -29,113 +29,20 @@ #include #include -#include -#include -#include -#include namespace mapnik { namespace geometry { +using coordinate_type = double; -namespace detail { - -template -struct closest_point +struct closest_point_result { - using coordinate_type = T; - using result_type = boost::geometry::closest_point_result>; - - closest_point(mapnik::geometry::point const& pt) - : pt_(pt) {} - - result_type operator() (mapnik::geometry::geometry_empty const&) const - { - return result_type(); // FIXME: consider std::optional - } - - result_type operator() (mapnik::geometry::point const& pt) const - { - result_type info; - boost::geometry::closest_point(pt_ ,pt, info); - return info; - } - - result_type operator() (mapnik::geometry::line_string const& line) const - { - result_type info; - boost::geometry::closest_point(pt_ ,line, info); - return info; - } - - result_type operator() (mapnik::geometry::polygon const& poly) const - { - result_type info; - if (boost::geometry::within(pt_, poly)) - { - info.closest_point = pt_; - info.distance = 0.0; - return info; - } - bool first = true; - for (auto const& ring : poly) - { - result_type ring_info; - boost::geometry::closest_point(pt_ ,ring, ring_info); - if (first) - { - first = false; - info = std::move(ring_info); - } - else if (ring_info.distance < info.distance) - { - info = std::move(ring_info); - } - } - return info; - } - - - - // Multi* + GeometryCollection - result_type operator() (mapnik::geometry::geometry const& geom) const - { - return mapnik::util::apply_visitor(*this, geom); - } - - template - result_type operator() (MultiGeometry const& multi_geom) const - { - result_type info; - bool first = true; - for (auto const& geom : multi_geom) - { - if (first) - { - first = false; - info = std::move(operator()(geom)); - } - else - { - auto sub_info = operator()(geom); - if (sub_info.distance < info.distance) - { - info = std::move(sub_info); - } - } - } - return info; - } - - mapnik::geometry::point pt_; + double x = 0.0; + double y = 0.0; + double distance = -1.0; }; -} - +using result_type = closest_point_result; template -inline typename detail::closest_point::result_type -closest_point(T1 const& geom, mapnik::geometry::point const& pt) -{ - return detail::closest_point(pt)(geom); -} +MAPNIK_DECL result_type closest_point(T1 const& geom, mapnik::geometry::point const& pt); }} diff --git a/src/build.py b/src/build.py index 13c5a9b5d..f80af2637 100644 --- a/src/build.py +++ b/src/build.py @@ -170,6 +170,7 @@ source = Split( datasource_cache_static.cpp debug.cpp geometry/box2d.cpp + geometry/closest_point.cpp geometry/reprojection.cpp geometry/envelope.cpp expression_node.cpp diff --git a/src/geometry/closest_point.cpp b/src/geometry/closest_point.cpp new file mode 100644 index 000000000..60d68c458 --- /dev/null +++ b/src/geometry/closest_point.cpp @@ -0,0 +1,160 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2017 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ +#include + +#if BOOST_VERSION >= 106200 +#include +#include +#include +#include +#include + +namespace mapnik { namespace geometry { + +namespace detail { + +template +struct closest_point +{ + using coordinate_type = T; + using info_type = boost::geometry::closest_point_result>; + + closest_point(mapnik::geometry::point const& pt) + : pt_(pt) {} + + result_type operator() (mapnik::geometry::geometry_empty const&) const + { + return result_type(); + } + + result_type operator() (mapnik::geometry::point const& pt) const + { + info_type info; + boost::geometry::closest_point(pt_, pt, info); + return result_type{info.closest_point.x, info.closest_point.y, info.distance}; + } + + result_type operator() (mapnik::geometry::line_string const& line) const + { + info_type info; + boost::geometry::closest_point(pt_ ,line, info); + return result_type{info.closest_point.x, info.closest_point.y, info.distance}; + } + + result_type operator() (mapnik::geometry::polygon const& poly) const + { + info_type info; + if (boost::geometry::within(pt_, poly)) + { + return result_type { pt_.x, pt_.y, 0.0 }; + } + bool first = true; + for (auto const& ring : poly) + { + info_type ring_info; + boost::geometry::closest_point(pt_ ,ring, ring_info); + if (first) + { + first = false; + info = std::move(ring_info); + } + else if (ring_info.distance < info.distance) + { + info = std::move(ring_info); + } + } + return result_type{info.closest_point.x, info.closest_point.y, info.distance}; + } + + + + // Multi* + GeometryCollection + result_type operator() (mapnik::geometry::geometry const& geom) const + { + return mapnik::util::apply_visitor(*this, geom); + } + + template + result_type operator() (MultiGeometry const& multi_geom) const + { + result_type result; + bool first = true; + for (auto const& geom : multi_geom) + { + if (first) + { + first = false; + result = std::move(operator()(geom)); + } + else + { + auto sub_result = operator()(geom); + if (sub_result.distance < result.distance) + { + result = std::move(sub_result); + } + } + } + return result; + } + mapnik::geometry::point pt_; +}; + +} + +template +MAPNIK_DECL result_type +closest_point(T1 const& geom, mapnik::geometry::point const& pt) +{ + return detail::closest_point(pt)(geom); +} + +template MAPNIK_DECL result_type +closest_point(geometry const&, point const&); + +template MAPNIK_DECL result_type +closest_point(point const&, point const&); + +template MAPNIK_DECL result_type +closest_point(line_string const&, point const&); + +template MAPNIK_DECL result_type +closest_point(polygonconst&, point const&); + +template MAPNIK_DECL result_type +closest_point(multi_pointconst&, point const&); + +template MAPNIK_DECL result_type +closest_point(multi_line_stringconst&, point const&); + +template MAPNIK_DECL result_type +closest_point(multi_polygonconst&, point const&); + +template MAPNIK_DECL result_type +closest_point(geometry_empty const&, point const&); + +template MAPNIK_DECL result_type +closest_point(geometry_collection const&, point const&); + +}} + +#endif //