diff --git a/include/boost/geometry/extensions/index/distance_calc.hpp b/include/boost/geometry/extensions/index/distance_calc.hpp new file mode 100644 index 000000000..22001e2e0 --- /dev/null +++ b/include/boost/geometry/extensions/index/distance_calc.hpp @@ -0,0 +1,188 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// +// Boost.SpatialIndex - Spatial index distances calculators used in nearest query +// +// Copyright 2011 Adam Wulkiewicz. +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_EXTENSIONS_INDEX_DISTANCE_CALC_HPP +#define BOOST_GEOMETRY_EXTENSIONS_INDEX_DISTANCE_CALC_HPP + +namespace boost { namespace geometry { namespace index { + +namespace detail { + +//TODO: awulkiew - consider storing values instead of const references +// it may be faster and it eliminates problems with storing of references to temporaries + +struct distance_near_tag {}; +struct distance_far_tag {}; +struct distance_centroid_tag {}; + +template +struct distance_xxx + : nonassignable +{ + typedef typename index::traits::coordinate_type::type coordinate_type; + typedef typename geometry::default_distance_result::type distance_type; + + inline explicit distance_xxx( + Point const& p, + coordinate_type const& distance_near = coordinate_type(0), + coordinate_type const& distance_far = std::numeric_limits::max() + ) + : point(p) + , comparable_near(distance_near * distance_near) + , comparable_far(distance_far * distance_far) + {} + + Point const& point; + distance_type comparable_near; + distance_type comparable_far; +}; + +} // namespace detail + +template +inline detail::distance_xxx +distance( + Point const& p, + typename index::traits::coordinate_type::type const& near + = typename index::traits::coordinate_type::type(0), + typename index::traits::coordinate_type::type const& far + = std::numeric_limits::type>::max() +) +{ + return detail::detail::distance_xxx(p, near, far); +} + +template +inline detail::distance_xxx +distance_near( + Point const& p, + typename index::traits::coordinate_type::type const& near + = typename index::traits::coordinate_type::type(0), + typename index::traits::coordinate_type::type const& far + = std::numeric_limits::type>::max() +) +{ + return detail::detail::distance_xxx(p, near, far); +} + +template +inline detail::distance_xxx +distance_far( + Point const& p, + typename index::traits::coordinate_type::type const& near + = typename index::traits::coordinate_type::type(0), + typename index::traits::coordinate_type::type const& far + = std::numeric_limits::type>::max() + ) +{ + return detail::detail::distance_xxx(p, near, far); +} + +template +inline detail::distance_xxx +distance_centroid( + Point const& p, + typename index::traits::coordinate_type::type const& near + = typename index::traits::coordinate_type::type(0), + typename index::traits::coordinate_type::type const& far + = std::numeric_limits::type>::max() + ) +{ + return detail::detail::distance_xxx(p, near, far); +} + +namespace detail +{ + +template +struct distance_calc +{ + typedef typename geometry::default_distance_result::type distance_type; + + static inline distance_type apply(Point const& p, Indexable const& i) + { + return index::mindist(p, i); + } +}; + +template +struct distance_calc< + detail::distance_xxx, + Indexable> +{ + typedef typename geometry::default_distance_result::type distance_type; + + static inline distance_type apply( + detail::distance_xxx const& d, + Indexable const& i) + { + return index::mindist(d.point, i); + } +}; + +// TODO distance_centroid + +template +struct distance_calc< + detail::distance_xxx, + Indexable> +{ + typedef typename geometry::default_distance_result::type distance_type; + + static inline distance_type apply( + detail::distance_xxx const& d, + Indexable const& i) + { + return index::maxdist(d.point, i); + } +}; + +template +struct is_distance_ok +{ + template + static inline bool apply(Point const&, DistanceType const&) + { + return true; + } +}; + +template +struct is_distance_ok< detail::distance_xxx > +{ + template + static inline bool apply( + detail::distance_xxx const& dx, + DistanceType const& d) + { + return dx.comparable_near <= d && d <= dx.comparable_far; + } +}; + +} // namespace detail + +template +inline typename detail::distance_calc::distance_type +distance_calc(PointData const& p, Indexable const& i) +{ + return detail::distance_calc + ::apply(p, i); +} + +template +inline bool +is_distance_ok(PointData const& p, DistanceType const& d) +{ + return detail::is_distance_ok + ::apply(p, d); +} + +}}} // namespace boost::geometry::index + +#endif // BOOST_GEOMETRY_EXTENSIONS_INDEX_DISTANCE_CALC_HPP diff --git a/include/boost/geometry/extensions/index/predicates.hpp b/include/boost/geometry/extensions/index/predicates.hpp index fa82bfb29..6ce3d3667 100644 --- a/include/boost/geometry/extensions/index/predicates.hpp +++ b/include/boost/geometry/extensions/index/predicates.hpp @@ -96,7 +96,11 @@ namespace detail // predicate check -// TODO: use empty definitions here + MPL_ASSERT +// TODO: use empty definitions here + MPL_ASSERT ? +// implement default values predicates applied to values in leafs, as a function/functor as simple as possible +// bool fun(Value const& v); +// distinguish between geometries and other types by use of geometry::tag +// in predicate_check_default<..., GeomTag> -> predicate_check_default<..., void> template struct predicate_check diff --git a/include/boost/geometry/extensions/index/rtree/visitors/nearest.hpp b/include/boost/geometry/extensions/index/rtree/visitors/nearest.hpp index 27f5b4c72..2f540c439 100644 --- a/include/boost/geometry/extensions/index/rtree/visitors/nearest.hpp +++ b/include/boost/geometry/extensions/index/rtree/visitors/nearest.hpp @@ -14,6 +14,8 @@ #include #include +#include + #include namespace boost { namespace geometry { namespace index { @@ -32,37 +34,37 @@ public: typedef typename geometry::default_distance_result::type distance_type; inline nearest_one() - : comp_mindist(std::numeric_limits::max()) + : comp_dist(std::numeric_limits::max()) {} - inline void store(Value const& val, distance_type const& curr_mindist) + inline void store(Value const& val, distance_type const& curr_comp_dist) { - if ( curr_mindist < comp_mindist ) + if ( curr_comp_dist < comp_dist ) { - comp_mindist = curr_mindist; + comp_dist = curr_mindist; value = val; } } - inline bool is_mindist_valid() const + inline bool is_comparable_distance_valid() const { - return comp_mindist < std::numeric_limits::max(); + return comp_dist < std::numeric_limits::max(); } - inline distance_type mindist() const + inline distance_type comparable_distance() const { - return comp_mindist; + return comp_dist; } inline size_t get(Value & v) { v = value; - return is_mindist_valid() ? 1 : 0; + return is_comparable_distance_valid() ? 1 : 0; } private: Value value; - distance_type comp_mindist; + distance_type comp_dist; }; template @@ -79,9 +81,9 @@ public: m_neighbors.reserve(m_count + 1); } - inline void store(Value const& val, distance_type const& curr_mindist) + inline void store(Value const& val, distance_type const& curr_comp_dist) { - m_neighbors.push_back(std::make_pair(curr_mindist, val)); + m_neighbors.push_back(std::make_pair(curr_comp_dist, val)); std::sort(m_neighbors.begin(), m_neighbors.end(), neighbors_less); if ( m_count < m_neighbors.size() ) @@ -93,12 +95,12 @@ public: // check the furthest distance at the first place, before push_back() } - inline bool is_mindist_valid() const + inline bool is_comparable_distance_valid() const { return m_neighbors.size() == m_count; } - inline distance_type mindist() const + inline distance_type comparable_distance() const { return m_neighbors.size() < m_count ? std::numeric_limits::max() : @@ -134,10 +136,7 @@ template < typename Box, typename Point, typename Predicates, - typename Result = typename geometry::default_distance_result< - Point, - typename Translator::indexable_type - >::type + typename Result > class nearest : public rtree::visitor::type @@ -230,11 +229,11 @@ private: inline void prune_nodes(ActiveBranchList & abl) const { // if some value were found - if ( m_result.is_mindist_valid() ) + if ( m_result.is_comparable_distance_valid() ) { // prune if box's mindist is further than value's mindist while ( !abl.empty() && - m_result.mindist() < abl.back().first ) + m_result.comparable_distance() < abl.back().first ) { abl.pop_back(); }