diff --git a/include/boost/geometry/index/detail/distance_predicates.hpp b/include/boost/geometry/index/detail/distance_predicates.hpp index 9544ba54c..5ab66ca1a 100644 --- a/include/boost/geometry/index/detail/distance_predicates.hpp +++ b/include/boost/geometry/index/detail/distance_predicates.hpp @@ -15,35 +15,12 @@ #include #include #include - -#include +#include #include -// TODO - optimization -// For Boxes and Points all types of distances may be calculated -// - near, far and centroid. For points those are the same distance -// calculate them for Boxes only! -// for Points calculate only 1 distance - namespace boost { namespace geometry { namespace index { namespace detail { -// ------------------------------------------------------------------ // -// distance_predicates_type -// ------------------------------------------------------------------ // - -template -struct distance_predicates_type -{ - typedef void type; -}; - -template -struct distance_predicates_type< detail::nearest > -{ - typedef DistancePredicates type; -}; - // ------------------------------------------------------------------ // // relations // ------------------------------------------------------------------ // @@ -116,766 +93,66 @@ struct relation< to_furthest > }; // ------------------------------------------------------------------ // -// distance predicates +// calculate_distance // ------------------------------------------------------------------ // -//template -//struct unbounded -// : nonassignable -//{ -// inline explicit unbounded(PointRelation const& pr) -// : point_relation(pr) -// {} -// -// PointRelation point_relation; -//}; -// -//template -//struct min_bounded -// : nonassignable -//{ -// typedef typename detail::relation::value_type point_type; -// typedef typename geometry::default_distance_result::type distance_type; -// -// inline min_bounded(PointRelation const& pr, MinRelation const& min_rel) -// : point_relation(pr) -// , comparable_min( -// relation::value(min_rel) * -// relation::value(min_rel) ) -// {} -// -// PointRelation point_relation; -// distance_type comparable_min; -//}; -// -//template -//struct max_bounded -// : nonassignable -//{ -// typedef typename detail::relation::value_type point_type; -// typedef typename geometry::default_distance_result::type distance_type; -// -// inline max_bounded(PointRelation const& pr, MaxRelation const& max_rel) -// : point_relation(pr) -// , comparable_max( -// relation::value(max_rel) * -// relation::value(max_rel) ) -// {} -// -// PointRelation point_relation; -// distance_type comparable_max; -//}; -// -//template -//struct bounded -// : nonassignable -//{ -// typedef typename detail::relation::value_type point_type; -// typedef typename geometry::default_distance_result::type distance_type; -// -// inline bounded(PointRelation const& pr, MinRelation const& min_rel, MaxRelation const& max_rel) -// : point_relation(pr) -// , comparable_min( -// relation::value(min_rel) * -// relation::value(min_rel) ) -// , comparable_max( -// relation::value(max_rel) * -// relation::value(max_rel) ) -// {} -// -// PointRelation point_relation; -// distance_type comparable_min; -// distance_type comparable_max; -//}; - -// ------------------------------------------------------------------ // -// point_relation trait -// ------------------------------------------------------------------ // - -template -struct point_relation +template +struct calculate_distance { - typedef PointRelation type; + BOOST_MPL_ASSERT_MSG((false), INVALID_PREDICATE_OR_TAG, (calculate_distance)); }; -//template -//struct point_relation< detail::unbounded > -//{ -// typedef PointRelation type; -//}; -// -//template -//struct point_relation< detail::min_bounded > -//{ -// typedef PointRelation type; -//}; -// -//template -//struct point_relation< detail::max_bounded > -//{ -// typedef PointRelation type; -//}; -// -//template -//struct point_relation< detail::bounded > -//{ -// typedef PointRelation type; -//}; - -// ------------------------------------------------------------------ // -// helpers -// ------------------------------------------------------------------ // - -// algorithms - -// cdist - -template -struct cdist -{ - T value; -}; - -// cdist_merge - -template -struct cdist_merge -{ - typedef typename detail::tuples::add_unique< - CDistTuple, - CDist - >::type type; -}; - -template -struct cdist_merge< - cdist, - cdist > -{ - typedef boost::tuple< - cdist, - cdist - > type; -}; - -template -struct cdist_merge< - cdist, - cdist > -{ - typedef cdist type; -}; - -// cdist_value_type - -template -struct cdist_value -{ - typedef typename cdist_value< - typename boost::tuples::element<0, CDistTuple>::type - >::type type; - - template - static inline type & get(CDistTuple & cdtup) - { - return boost::get< - tuples::find_index< - CDistTuple, - cdist - >::value - >(cdtup).value; - } - - template - static inline type const& get(CDistTuple const& cdtup) - { - return boost::get< - tuples::find_index< - CDistTuple, - cdist - >::value - >(cdtup).value; - } -}; - -template -struct cdist_value< - cdist -> -{ - typedef T type; - - template - static inline type & get(cdist & cd) - { - BOOST_MPL_ASSERT_MSG( - (boost::is_same< cdist, cdist >::value), - TAGS_DO_NOT_MATCH, - (cdist_value)); - - return cd.value; - } - - template - static inline type const& get(cdist const& cd) - { - BOOST_MPL_ASSERT_MSG( - (boost::is_same< cdist, cdist >::value), - TAGS_DO_NOT_MATCH, - (cdist_value)); - - return cd.value; - } -}; - -// distances_calc_impl_rel - -template -struct distances_calc_impl_rel -{ - BOOST_MPL_ASSERT_MSG( - (false), - NOT_IMPLEMENTED_FOR_THIS_RELATION, - (distances_calc_impl_rel)); -}; - -template -struct distances_calc_impl_rel< - cdist -> -{ - template - typename geometry::default_distance_result::type - static inline apply(Point const& p, Indexable const& i) - { - return index::detail::comparable_distance_near(p, i); - } -}; - -template -struct distances_calc_impl_rel< - cdist -> -{ - template - typename geometry::default_distance_result::type - static inline apply(Point const& p, Indexable const& i) - { - return index::detail::comparable_distance_centroid(p, i); - } -}; - -template -struct distances_calc_impl_rel< - cdist -> -{ - template - typename geometry::default_distance_result::type - static inline apply(Point const& p, Indexable const& i) - { - return index::detail::comparable_distance_far(p, i); - } -}; - -// distances_calc_impl_tuple - -template -struct distances_calc_impl_tuple -{ - // TODO MPL ASSERT 0 < N - static inline void apply(Distances & d, Point const& p, Indexable const&i) - { - boost::get(d).value = - distances_calc_impl_rel< - typename boost::tuples::element::type - >::apply(p, i); - - distances_calc_impl_tuple< - Distances, - Point, - Indexable, - N - 1 - >::apply(d, p, i); - } -}; - -template -struct distances_calc_impl_tuple -{ - static inline void apply(Distances & d, Point const& p, Indexable const&i) - { - boost::get<0>(d).value = - distances_calc_impl_rel< - typename boost::tuples::element<0, Distances>::type - >::apply(p, i); - } -}; - -// distances_calc_impl - -template -struct distances_calc_impl -{ - static inline void apply(Distances & d, Point const& p, Indexable const&i) - { - distances_calc_impl_tuple< - Distances, - Point, - Indexable, - boost::tuples::length::value - >::apply(d, p, i); - } -}; - -template -struct distances_calc_impl< - cdist, - Point, - Indexable -> -{ - static inline void apply(cdist & d, Point const& p, Indexable const&i) - { - d.value = distances_calc_impl_rel< - cdist - >::apply(p, i); - } -}; - -// ------------------------------------------------------------------ // -// distance_calc and distances_predicates_check -// ------------------------------------------------------------------ // - +// this handles nearest() with default Point parameter, to_nearest() and bounds template -struct distances_calc +struct calculate_distance< nearest, Indexable, Tag > { - BOOST_MPL_ASSERT_MSG( - (false), - NOT_IMPLEMENTED_FOR_THIS_TAG, - (distances_calc)); -}; + typedef detail::relation relation; + typedef typename relation::value_type point_type; + typedef typename geometry::default_distance_result::type result_type; -template -struct distances_predicates_check -{ - BOOST_MPL_ASSERT_MSG( - (false), - NOT_IMPLEMENTED_FOR_THIS_TAG, - (distances_predicates_check)); -}; - -// ------------------------------------------------------------------ // -// distance_calc for value_tag -// ------------------------------------------------------------------ // - -template -struct distances_calc -{ - typedef typename detail::relation::value_type point_type; - typedef typename detail::relation::tag point_relation_tag; - typedef typename geometry::default_distance_result::type distance_type; - - typedef detail::cdist result_type; - - static inline result_type apply(PointRelation const& p, Indexable const& i) - { - result_type res; - distances_calc_impl - ::apply(res, relation::value(p), i); - return res; - } -}; - -//template -//struct distances_calc< -// detail::unbounded, -// Indexable, -// value_tag -//> -//{ -// typedef typename detail::relation::value_type point_type; -// typedef typename detail::relation::tag point_relation_tag; -// typedef typename geometry::default_distance_result::type distance_type; -// -// typedef detail::cdist result_type; -// -// static inline result_type apply(detail::unbounded const& pp, Indexable const& i) -// { -// result_type res; -// distances_calc_impl -// ::apply(res, relation::value(pp.point_relation), i); -// return res; -// } -//}; -// -//template -//struct distances_calc< -// detail::min_bounded, -// Indexable, -// value_tag -//> -//{ -// typedef typename detail::relation::value_type point_type; -// typedef typename detail::relation::tag point_relation_tag; -// typedef typename geometry::default_distance_result::type distance_type; -// typedef typename detail::relation::tag min_relation_tag; -// -// typedef typename detail::cdist_merge< -// cdist, -// cdist -// >::type result_type; -// -// static inline result_type apply(detail::min_bounded const& pp, Indexable const& i) -// { -// result_type res; -// distances_calc_impl -// ::apply(res, relation::value(pp.point_relation), i); -// return res; -// } -//}; -// -//template -//struct distances_calc< -// detail::max_bounded, -// Indexable, -// value_tag -//> -//{ -// typedef typename detail::relation::value_type point_type; -// typedef typename detail::relation::tag point_relation_tag; -// typedef typename geometry::default_distance_result::type distance_type; -// typedef typename detail::relation::tag max_relation_tag; -// -// typedef typename detail::cdist_merge< -// cdist, -// cdist -// >::type result_type; -// -// static inline result_type apply(detail::max_bounded const& pp, Indexable const& i) -// { -// result_type res; -// distances_calc_impl -// ::apply(res, relation::value(pp.point_relation), i); -// return res; -// } -//}; -// -//template -//struct distances_calc< -// detail::bounded, -// Indexable, -// value_tag -//> -//{ -// typedef typename detail::relation::value_type point_type; -// typedef typename detail::relation::tag point_relation_tag; -// typedef typename geometry::default_distance_result::type distance_type; -// typedef typename detail::relation::tag min_relation_tag; -// typedef typename detail::relation::tag max_relation_tag; -// -// typedef typename detail::cdist_merge< -// typename detail::cdist_merge< -// cdist, -// cdist -// >::type, -// cdist -// >::type result_type; -// -// static inline result_type apply( -// detail::bounded const& pp, -// Indexable const& i) -// { -// result_type res; -// distances_calc_impl -// ::apply(res, relation::value(pp.point_relation), i); -// return res; -// } -//}; - -// ------------------------------------------------------------------ // -// distance_predicates_check for value_tag -// ------------------------------------------------------------------ // - -template -struct distances_predicates_check -{ - template - static inline bool apply(PointRelation const&, Distances const&) + static inline bool apply(nearest const& p, Indexable const& i, result_type & result) { + result = index::detail::comparable_distance_near(relation::value(p.point_or_relation), i); return true; } }; -//template -//struct distances_predicates_check< -// detail::unbounded, -// Indexable, -// value_tag -//> -//{ -// template -// static inline bool apply(detail::unbounded const&, Distances const&) -// { -// return true; -// } -//}; -// -//template -//struct distances_predicates_check< -// detail::min_bounded, -// Indexable, -// value_tag -//> -//{ -// typedef typename detail::relation::tag min_relation_tag; -// -// template -// static inline bool apply( -// detail::min_bounded const& pred, -// Distances const& d) -// { -// return pred.comparable_min <= -// detail::cdist_value::template get(d); -// } -//}; -// -//template -//struct distances_predicates_check< -// detail::max_bounded, -// Indexable, -// value_tag -//> -//{ -// typedef typename detail::relation::tag max_relation_tag; -// -// template -// static inline bool apply( -// detail::max_bounded const& pred, -// Distances const& d) -// { -// return pred.comparable_max <= -// detail::cdist_value::template get(d); -// } -//}; -// -//template -//struct distances_predicates_check< -// detail::bounded, -// Indexable, -// value_tag -//> -//{ -// typedef typename detail::relation::tag min_relation_tag; -// typedef typename detail::relation::tag max_relation_tag; -// -// template -// static inline bool apply( -// detail::bounded const& pred, -// Distances const& d) -// { -// return pred.comparable_min -// <= detail::cdist_value::template get(d) -// && detail::cdist_value::template get(d) -// <= pred.comparable_max; -// } -//}; - -// ------------------------------------------------------------------ // -// distance_calc for bounds_tag -// ------------------------------------------------------------------ // - -template -struct distances_calc< - PointRelation, - Box, - bounds_tag> +template +struct calculate_distance< nearest< to_centroid >, Indexable, value_tag> { - typedef typename detail::relation::value_type point_type; - typedef typename geometry::default_distance_result::type distance_type; + typedef Point point_type; + typedef typename geometry::default_distance_result::type result_type; - typedef detail::cdist result_type; - - static inline result_type apply(PointRelation const& p, Box const& i) - { - result_type res; - distances_calc_impl - ::apply(res, relation::value(p), i); - return res; - } -}; - -//template -//struct distances_calc< -// detail::unbounded, -// Box, -// bounds_tag -//> -//{ -// typedef typename detail::relation::value_type point_type; -// typedef typename geometry::default_distance_result::type distance_type; -// -// typedef detail::cdist result_type; -// -// static inline result_type apply(detail::unbounded const& pp, Box const& i) -// { -// result_type res; -// distances_calc_impl -// ::apply(res, relation::value(pp.point_relation), i); -// return res; -// } -//}; -// -//template -//struct distances_calc< -// detail::min_bounded, -// Box, -// bounds_tag -//> -//{ -// typedef typename detail::relation::value_type point_type; -// typedef typename geometry::default_distance_result::type distance_type; -// -// typedef typename detail::cdist_merge< -// cdist, -// cdist -// >::type result_type; -// -// static inline result_type apply(detail::min_bounded const& pp, Box const& i) -// { -// result_type res; -// distances_calc_impl -// ::apply(res, relation::value(pp.point_relation), i); -// return res; -// } -//}; -// -//template -//struct distances_calc< -// detail::max_bounded, -// Box, -// bounds_tag -//> -//{ -// typedef typename detail::relation::value_type point_type; -// typedef typename geometry::default_distance_result::type distance_type; -// -// typedef cdist result_type; -// -// static inline result_type apply(detail::max_bounded const& pp, Box const& i) -// { -// result_type res; -// distances_calc_impl -// ::apply(res, relation::value(pp.point_relation), i); -// return res; -// } -//}; -// -//template -//struct distances_calc< -// detail::bounded, -// Box, -// bounds_tag -//> -//{ -// typedef typename detail::relation::value_type point_type; -// typedef typename geometry::default_distance_result::type distance_type; -// -// typedef typename detail::cdist_merge< -// cdist, -// cdist -// >::type result_type; -// -// static inline result_type apply(detail::bounded const& pp, Box const& i) -// { -// result_type res; -// distances_calc_impl -// ::apply(res, relation::value(pp.point_relation), i); -// return res; -// } -//}; - -// ------------------------------------------------------------------ // -// distance_predicates_check for bounds_tag -// ------------------------------------------------------------------ // - -template -struct distances_predicates_check< - PointRelation, - Box, - bounds_tag> -{ - template - static inline bool apply(PointRelation const&, Distances const&) + static inline bool apply(nearest< to_centroid > const& p, Indexable const& i, result_type & result) { + result = index::detail::comparable_distance_centroid(p.point_or_relation.value, i); return true; } }; -//template -//struct distances_predicates_check< -// detail::unbounded, -// Box, -// bounds_tag> -//{ -// template -// static inline bool apply( -// detail::unbounded const&, -// Distances const&) -// { -// return true; -// } -//}; -// -//template -//struct distances_predicates_check< -// detail::min_bounded, -// Box, -// bounds_tag> -//{ -// template -// static inline bool apply( -// detail::min_bounded const& pred, -// Distances const& d) -// { -// return pred.comparable_min -// <= cdist_value::template get(d); -// } -//}; -// -//template -//struct distances_predicates_check< -// detail::max_bounded, -// Box, -// bounds_tag> -//{ -// template -// static inline bool apply( -// detail::max_bounded const& pred, -// Distances const& d) -// { -// return cdist_value::template get(d) -// <= pred.comparable_max; -// } -//}; -// -//template -//struct distances_predicates_check< -// detail::bounded, -// Box, -// bounds_tag> -//{ -// template -// static inline bool apply( -// detail::bounded const& pred, -// Distances const& d) -// { -// return pred.comparable_min -// <= cdist_value::template get(d) -// && cdist_value::template get(d) -// <= pred.comparable_max; -// } -//}; +template +struct calculate_distance< nearest< to_furthest >, Indexable, value_tag> +{ + typedef Point point_type; + typedef typename geometry::default_distance_result::type result_type; + + static inline bool apply(nearest< to_furthest > const& p, Indexable const& i, result_type & result) + { + result = index::detail::comparable_distance_far(p.point_or_relation.value, i); + return true; + } +}; + +template +struct calculate_distance< path, Indexable, Tag> +{ + typedef typename geometry::default_length_result::type result_type; + + static inline bool apply(path const& p, Indexable const& i, result_type & result) + { + return index::detail::path_intersection(i, p.linestring, result); + } +}; }}}} // namespace boost::geometry::index::detail diff --git a/include/boost/geometry/index/detail/predicates.hpp b/include/boost/geometry/index/detail/predicates.hpp index 3b463bda5..29e0a658f 100644 --- a/include/boost/geometry/index/detail/predicates.hpp +++ b/include/boost/geometry/index/detail/predicates.hpp @@ -129,14 +129,25 @@ struct not_within Geometry geometry; }; -template +template struct nearest { - nearest(DistancePredicates const& dpred, unsigned k) - : distance_predicates(dpred) + nearest(PointOrRelation const& por, unsigned k) + : point_or_relation(por) , count(k) {} - DistancePredicates distance_predicates; + PointOrRelation point_or_relation; + unsigned count; +}; + +template +struct path +{ + path(Linestring const& ls, unsigned k) + : linestring(ls) + , count(k) + {} + Linestring linestring; unsigned count; }; @@ -377,6 +388,16 @@ struct predicate_check, value_tag> } }; +template +struct predicate_check, value_tag> +{ + template + static inline bool apply(path const&, Value const&, Box const&) + { + return true; + } +}; + // ------------------------------------------------------------------ // // predicate_check_default for bounds // ------------------------------------------------------------------ // @@ -571,6 +592,16 @@ struct predicate_check, bounds_tag> } }; +template +struct predicate_check, bounds_tag> +{ + template + static inline bool apply(path const&, Value const&, Box const&) + { + return true; + } +}; + // ------------------------------------------------------------------ // // predicates_length // ------------------------------------------------------------------ // @@ -805,13 +836,19 @@ inline bool predicates_check(Predicates const& p, Value const& v, Indexable cons // predicates_is_nearest template -struct predicates_is_nearest +struct predicates_is_distance { static const unsigned value = 0; }; template -struct predicates_is_nearest< nearest > +struct predicates_is_distance< nearest > +{ + static const unsigned value = 1; +}; + +template +struct predicates_is_distance< path > { static const unsigned value = 1; }; @@ -819,46 +856,46 @@ struct predicates_is_nearest< nearest > // predicates_count_nearest template -struct predicates_count_nearest +struct predicates_count_distance { - static const unsigned value = predicates_is_nearest::value; + static const unsigned value = predicates_is_distance::value; }; //template -//struct predicates_count_nearest< std::pair > +//struct predicates_count_distance< std::pair > //{ -// static const unsigned value = predicates_is_nearest::value -// + predicates_is_nearest::value; +// static const unsigned value = predicates_is_distance::value +// + predicates_is_distance::value; //}; template -struct predicates_count_nearest_tuple +struct predicates_count_distance_tuple { static const unsigned value = - predicates_is_nearest::type>::value - + predicates_count_nearest_tuple::value; + predicates_is_distance::type>::value + + predicates_count_distance_tuple::value; }; template -struct predicates_count_nearest_tuple +struct predicates_count_distance_tuple { static const unsigned value = - predicates_is_nearest::type>::value; + predicates_is_distance::type>::value; }; //template -//struct predicates_count_nearest< boost::tuple > +//struct predicates_count_distance< boost::tuple > //{ -// static const unsigned value = predicates_count_nearest_tuple< +// static const unsigned value = predicates_count_distance_tuple< // boost::tuple, // boost::tuples::length< boost::tuple >::value // >::value; //}; template -struct predicates_count_nearest< boost::tuples::cons > +struct predicates_count_distance< boost::tuples::cons > { - static const unsigned value = predicates_count_nearest_tuple< + static const unsigned value = predicates_count_distance_tuple< boost::tuples::cons, boost::tuples::length< boost::tuples::cons >::value >::value; @@ -867,50 +904,50 @@ struct predicates_count_nearest< boost::tuples::cons > // predicates_find_nearest template -struct predicates_find_nearest +struct predicates_find_distance { - static const unsigned value = predicates_is_nearest::value ? 0 : 1; + static const unsigned value = predicates_is_distance::value ? 0 : 1; }; //template -//struct predicates_find_nearest< std::pair > +//struct predicates_find_distance< std::pair > //{ -// static const unsigned value = predicates_is_nearest::value ? 0 : -// (predicates_is_nearest::value ? 1 : 2); +// static const unsigned value = predicates_is_distance::value ? 0 : +// (predicates_is_distance::value ? 1 : 2); //}; template -struct predicates_find_nearest_tuple +struct predicates_find_distance_tuple { - static const bool is_found = predicates_find_nearest_tuple::is_found - || predicates_is_nearest::type>::value; + static const bool is_found = predicates_find_distance_tuple::is_found + || predicates_is_distance::type>::value; - static const unsigned value = predicates_find_nearest_tuple::is_found ? - predicates_find_nearest_tuple::value : - (predicates_is_nearest::type>::value ? + static const unsigned value = predicates_find_distance_tuple::is_found ? + predicates_find_distance_tuple::value : + (predicates_is_distance::type>::value ? N-1 : boost::tuples::length::value); }; template -struct predicates_find_nearest_tuple +struct predicates_find_distance_tuple { - static const bool is_found = predicates_is_nearest::type>::value; + static const bool is_found = predicates_is_distance::type>::value; static const unsigned value = is_found ? 0 : boost::tuples::length::value; }; //template -//struct predicates_find_nearest< boost::tuple > +//struct predicates_find_distance< boost::tuple > //{ -// static const unsigned value = predicates_find_nearest_tuple< +// static const unsigned value = predicates_find_distance_tuple< // boost::tuple, // boost::tuples::length< boost::tuple >::value // >::value; //}; template -struct predicates_find_nearest< boost::tuples::cons > +struct predicates_find_distance< boost::tuples::cons > { - static const unsigned value = predicates_find_nearest_tuple< + static const unsigned value = predicates_find_distance_tuple< boost::tuples::cons, boost::tuples::length< boost::tuples::cons >::value >::value; diff --git a/include/boost/geometry/index/detail/rtree/query_iterators.hpp b/include/boost/geometry/index/detail/rtree/query_iterators.hpp index 4482ae420..8d0dbdd9d 100644 --- a/include/boost/geometry/index/detail/rtree/query_iterators.hpp +++ b/include/boost/geometry/index/detail/rtree/query_iterators.hpp @@ -143,9 +143,9 @@ private: }; template -class nearest_query_iterator +class distance_query_iterator { - typedef visitors::nearest_query_incremental visitor_type; + typedef visitors::distance_query_incremental visitor_type; typedef typename visitor_type::node_pointer node_pointer; public: @@ -155,11 +155,11 @@ public: typedef typename Allocators::difference_type difference_type; typedef typename Allocators::const_pointer pointer; - inline nearest_query_iterator(Translator const& t, Predicates const& p) + inline distance_query_iterator(Translator const& t, Predicates const& p) : m_visitor(t, p) {} - inline nearest_query_iterator(node_pointer root, Translator const& t, Predicates const& p) + inline distance_query_iterator(node_pointer root, Translator const& t, Predicates const& p) : m_visitor(t, p) { detail::rtree::apply_visitor(m_visitor, *root); @@ -176,45 +176,45 @@ public: return boost::addressof(m_visitor.dereference()); } - nearest_query_iterator & operator++() + distance_query_iterator & operator++() { m_visitor.increment(); return *this; } - nearest_query_iterator operator++(int) + distance_query_iterator operator++(int) { - nearest_query_iterator temp = *this; + distance_query_iterator temp = *this; this->operator++(); return temp; } - friend bool operator==(nearest_query_iterator const& l, nearest_query_iterator const& r) + friend bool operator==(distance_query_iterator const& l, distance_query_iterator const& r) { return l.m_visitor == r.m_visitor; } - friend bool operator==(nearest_query_iterator const& l, end_query_iterator) + friend bool operator==(distance_query_iterator const& l, end_query_iterator) { return l.m_visitor.is_end(); } - friend bool operator==(end_query_iterator, nearest_query_iterator const& r) + friend bool operator==(end_query_iterator, distance_query_iterator const& r) { return r.m_visitor.is_end(); } - friend bool operator!=(nearest_query_iterator const& l, nearest_query_iterator const& r) + friend bool operator!=(distance_query_iterator const& l, distance_query_iterator const& r) { return !(l.m_visitor == r.m_visitor); } - friend bool operator!=(nearest_query_iterator const& l, end_query_iterator) + friend bool operator!=(distance_query_iterator const& l, end_query_iterator) { return !l.m_visitor.is_end(); } - friend bool operator!=(end_query_iterator, nearest_query_iterator const& r) + friend bool operator!=(end_query_iterator, distance_query_iterator const& r) { return !r.m_visitor.is_end(); } diff --git a/include/boost/geometry/index/detail/rtree/visitors/nearest_query.hpp b/include/boost/geometry/index/detail/rtree/visitors/nearest_query.hpp index b089c3b22..055040fd8 100644 --- a/include/boost/geometry/index/detail/rtree/visitors/nearest_query.hpp +++ b/include/boost/geometry/index/detail/rtree/visitors/nearest_query.hpp @@ -15,63 +15,13 @@ namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace visitors { -// TODO: awulkiew - maybe it's a good idea to check if curr_mindist < comp_mindist and then check predicates -// in store() or divide store() into 2 functions e.g. should_store() and store() -// - well not with this algorithm of storing k-th neighbor - -//template -//struct nearest_query_result_one -//{ -//public: -// typedef typename geometry::default_distance_result< -// Point, -// typename translator::indexable_type::type -// >::type distance_type; -// -// inline nearest_query_result_one(Value & value) -// : m_value(value) -// , m_comp_dist((std::numeric_limits::max)()) -// {} -// -// inline void store(Value const& val, distance_type const& curr_comp_dist) -// { -// if ( curr_comp_dist < m_comp_dist ) -// { -// m_comp_dist = curr_comp_dist; -// m_value = val; -// } -// } -// -// inline bool is_comparable_distance_valid() const -// { -// return m_comp_dist < (std::numeric_limits::max)(); -// } -// -// inline distance_type comparable_distance() const -// { -// return m_comp_dist; -// } -// -// inline size_t finish() -// { -// return is_comparable_distance_valid() ? 1 : 0; -// } -// -//private: -// Value & m_value; -// distance_type m_comp_dist; -//}; - -template -class nearest_query_result_k +template +class distance_query_result { public: - typedef typename geometry::default_distance_result< - Point, - typename indexable_type::type - >::type distance_type; + typedef DistanceType distance_type; - inline explicit nearest_query_result_k(size_t k, OutIt out_it) + inline explicit distance_query_result(size_t k, OutIt out_it) : m_count(k), m_out_it(out_it) { BOOST_GEOMETRY_INDEX_ASSERT(0 < m_count, "Number of neighbors should be greater than 0"); @@ -146,10 +96,10 @@ template < typename Box, typename Allocators, typename Predicates, - unsigned NearestPredicateIndex, - typename Result + unsigned DistancePredicateIndex, + typename OutIter > -class nearest_query +class distance_query : public rtree::visitor::type { public: @@ -159,31 +109,21 @@ public: typedef typename rtree::internal_node::type internal_node; typedef typename rtree::leaf::type leaf; - typedef index::detail::predicates_element nearest_predicate_access; - typedef typename index::detail::distance_predicates_type::type distance_predicates_type; + typedef index::detail::predicates_element nearest_predicate_access; + typedef typename nearest_predicate_access::type nearest_predicate_type; + typedef typename indexable_type::type indexable_type; - typedef index::detail::distances_calc node_distances_calc; - typedef typename node_distances_calc::result_type node_distances_type; - typedef index::detail::distances_predicates_check node_distances_predicates_check; - - typedef index::detail::distances_calc< - distance_predicates_type, - typename indexable_type::type, - index::detail::value_tag - > value_distances_calc; - typedef typename value_distances_calc::result_type value_distances_type; - typedef index::detail::distances_predicates_check< - distance_predicates_type, - typename indexable_type::type, - index::detail::value_tag - > value_distances_predicates_check; + typedef index::detail::calculate_distance calculate_value_distance; + typedef index::detail::calculate_distance calculate_node_distance; + typedef typename calculate_value_distance::result_type value_distance_type; + typedef typename calculate_node_distance::result_type node_distance_type; static const unsigned predicates_len = index::detail::predicates_length::value; - inline nearest_query(parameters_type const& parameters, Translator const& translator, Predicates const& pred, Result & r) + inline distance_query(parameters_type const& parameters, Translator const& translator, Predicates const& pred, OutIter out_it) : m_parameters(parameters), m_translator(translator) , m_pred(pred) - , m_result(r) + , m_result(nearest_predicate_access::get(m_pred).count, out_it) {} inline void operator()(internal_node const& n) @@ -193,7 +133,7 @@ public: // array of active nodes typedef typename index::detail::rtree::container_from_elements_type< elements_type, - std::pair + std::pair >::type active_branch_list_type; active_branch_list_type active_branch_list; @@ -210,25 +150,22 @@ public: if ( index::detail::predicates_check(m_pred, 0, it->first) ) { // calculate node's distance(s) for distance predicate - node_distances_type node_dist_data = node_distances_calc::apply(dist_pred(), it->first); - - // TODO: awulkiew - consider at first calculating near distance only, - // comparing it with m_result.comparable_distance if it's valid, - // after that calculate the rest of distances and check predicates - - // if current node is further than found neighbors - don't analyze it - if ( m_result.has_enough_neighbors() && - is_node_prunable(m_result.greatest_comparable_distance(), node_dist_data) ) + node_distance_type node_distance; + // if distance isn't ok - move to the next node + if ( !calculate_node_distance::apply(predicate(), it->first, node_distance) ) { continue; } - // if current node distance(s) meets distance predicate - if ( node_distances_predicates_check::apply(dist_pred(), node_dist_data) ) + // if current node is further than found neighbors - don't analyze it + if ( m_result.has_enough_neighbors() && + is_node_prunable(m_result.greatest_comparable_distance(), node_distance) ) { - // add current node's data into the list - active_branch_list.push_back( std::make_pair(node_dist_data, it->second) ); + continue; } + + // add current node's data into the list + active_branch_list.push_back( std::make_pair(node_distance, it->second) ); } } @@ -265,57 +202,46 @@ public: if ( index::detail::predicates_check(m_pred, *it, m_translator(*it)) ) { // calculate values distance for distance predicate - value_distances_type distances = value_distances_calc::apply(dist_pred(), m_translator(*it)); - - // TODO: awulkiew - consider at first calculating point relation distance only, - // comparing it with m_result.comparable_distance if it's valid, - // after that calculate the rest of distances and check predicates - - // if distance meets distance predicate - if ( value_distances_predicates_check::apply(dist_pred(), distances) ) + value_distance_type value_distance; + // if distance is ok + if ( calculate_value_distance::apply(predicate(), m_translator(*it), value_distance) ) { - typedef typename index::detail::point_relation::type point_relation_type; - typedef typename index::detail::relation::tag point_relation_tag; - // store value - m_result.store( - *it, - index::detail::cdist_value - ::template get(distances) - ); + m_result.store(*it, value_distance); } } } } + inline size_t finish() + { + return m_result.finish(); + } + private: static inline bool abl_less( - std::pair const& p1, - std::pair const& p2) + std::pair const& p1, + std::pair const& p2) { - return index::detail::cdist_value - ::template get(p1.first) - < index::detail::cdist_value - ::template get(p2.first); + return p1.first < p2.first; } template - static inline bool is_node_prunable(Distance const& greatest_dist, node_distances_type const& d) + static inline bool is_node_prunable(Distance const& greatest_dist, node_distance_type const& d) { - return greatest_dist <= index::detail::cdist_value - ::template get(d); + return greatest_dist <= d; } - inline distance_predicates_type const& dist_pred() const + nearest_predicate_type const& predicate() const { - return nearest_predicate_access::get(m_pred).distance_predicates; + return nearest_predicate_access::get(m_pred); } parameters_type const& m_parameters; Translator const& m_translator; Predicates m_pred; - Result & m_result; + distance_query_result m_result; }; template < @@ -325,9 +251,9 @@ template < typename Box, typename Allocators, typename Predicates, - unsigned NearestPredicateIndex + unsigned DistancePredicateIndex > -class nearest_query_incremental +class distance_query_incremental : public rtree::visitor::type { public: @@ -337,31 +263,14 @@ public: typedef typename rtree::internal_node::type internal_node; typedef typename rtree::leaf::type leaf; - typedef index::detail::predicates_element nearest_predicate_access; - typedef typename index::detail::distance_predicates_type::type distance_predicates_type; - typedef typename geometry::default_distance_result< - typename index::detail::relation< - typename index::detail::point_relation::type - >::value_type, - typename indexable_type::type - >::type value_distance_type; - - typedef index::detail::distances_calc node_distances_calc; - typedef typename node_distances_calc::result_type node_distances_type; - typedef index::detail::distances_predicates_check node_distances_predicates_check; - typedef typename index::detail::cdist_value::type node_distance_type; - - typedef index::detail::distances_calc< - distance_predicates_type, - typename indexable_type::type, - index::detail::value_tag - > value_distances_calc; - typedef typename value_distances_calc::result_type value_distances_type; - typedef index::detail::distances_predicates_check< - distance_predicates_type, - typename indexable_type::type, - index::detail::value_tag - > value_distances_predicates_check; + typedef index::detail::predicates_element nearest_predicate_access; + typedef typename nearest_predicate_access::type nearest_predicate_type; + typedef typename indexable_type::type indexable_type; + + typedef index::detail::calculate_distance calculate_value_distance; + typedef index::detail::calculate_distance calculate_node_distance; + typedef typename calculate_value_distance::result_type value_distance_type; + typedef typename calculate_node_distance::result_type node_distance_type; typedef typename Allocators::size_type size_type; typedef typename Allocators::const_reference const_reference; @@ -373,7 +282,7 @@ public: typedef typename internal_elements::const_iterator internal_iterator; typedef typename rtree::elements_type::type leaf_elements; - typedef std::pair branch_data; + typedef std::pair branch_data; typedef typename index::detail::rtree::container_from_elements_type< internal_elements, branch_data >::type active_branch_list_type; @@ -394,7 +303,7 @@ public: }; typedef std::vector internal_stack_type; - inline nearest_query_incremental(Translator const& translator, Predicates const& pred) + inline distance_query_incremental(Translator const& translator, Predicates const& pred) : m_translator(::boost::addressof(translator)) , m_pred(pred) , current_neighbor((std::numeric_limits::max)()) @@ -475,7 +384,7 @@ public: return (std::numeric_limits::max)() == current_neighbor; } - friend bool operator==(nearest_query_incremental const& l, nearest_query_incremental const& r) + friend bool operator==(distance_query_incremental const& l, distance_query_incremental const& r) { BOOST_ASSERT_MSG(l.current_neighbor != r.current_neighbor || (std::numeric_limits::max)() == l.current_neighbor || @@ -503,21 +412,22 @@ public: if ( index::detail::predicates_check(m_pred, 0, it->first) ) { // calculate node's distance(s) for distance predicate - node_distances_type node_dist_data = node_distances_calc::apply(dist_pred(), it->first); - - // if current node is further than found neighbors - don't analyze it - if ( max_count() <= neighbors.size() && - is_node_prunable(neighbors.back().first, node_dist_data) ) + node_distance_type node_distance; + // if distance isn't ok - move to the next node + if ( !calculate_node_distance::apply(predicate(), it->first, node_distance) ) { continue; } - // if current node distance(s) meets distance predicate - if ( node_distances_predicates_check::apply(dist_pred(), node_dist_data) ) + // if current node is further than found neighbors - don't analyze it + if ( max_count() <= neighbors.size() && + is_node_prunable(neighbors.back().first, node_distance) ) { - // add current node's data into the list - internal_stack.back().branches.push_back( std::make_pair(node_dist_data, it->second) ); + continue; } + + // add current node's data into the list + internal_stack.back().branches.push_back( std::make_pair(node_distance, it->second) ); } } @@ -547,22 +457,14 @@ public: if ( index::detail::predicates_check(m_pred, *it, (*m_translator)(*it)) ) { // calculate values distance for distance predicate - value_distances_type distances = value_distances_calc::apply(dist_pred(), (*m_translator)(*it)); - - // if distance meets distance predicate - if ( value_distances_predicates_check::apply(dist_pred(), distances) ) + value_distance_type value_distance; + // if distance is ok + if ( calculate_value_distance::apply(predicate(), (*m_translator)(*it), value_distance) ) { - typedef typename index::detail::point_relation::type point_relation_type; - typedef typename index::detail::relation::tag point_relation_tag; - - // store value if it's closer than the furthest neighbour - value_distance_type dist = index::detail::cdist_value - ::template get(distances); - // if there is not enough values or current value is closer than furthest neighbour - if ( not_enough_neighbors || dist < greatest_distance ) + if ( not_enough_neighbors || value_distance < greatest_distance ) { - neighbors.push_back(std::make_pair(dist, boost::addressof(*it))); + neighbors.push_back(std::make_pair(value_distance, boost::addressof(*it))); } } } @@ -576,11 +478,10 @@ public: } private: - static inline bool abl_less(std::pair const& p1, - std::pair const& p2) + static inline bool abl_less(std::pair const& p1, + std::pair const& p2) { - return index::detail::cdist_value::template get(p1.first) - < index::detail::cdist_value::template get(p2.first); + return p1.first < p2.first; } static inline bool neighbors_less(std::pair const& p1, @@ -599,8 +500,7 @@ private: if ( first->branches.size() <= first->current_branch ) continue; - node_distance_type curr_dist = index::detail::cdist_value - ::template get(first->branches[first->current_branch].first); + node_distance_type curr_dist = first->branches[first->current_branch].first; if ( curr_dist < result ) result = curr_dist; } @@ -608,15 +508,9 @@ private: } template - static inline bool is_node_prunable(Distance const& greatest_dist, node_distances_type const& d) + static inline bool is_node_prunable(Distance const& greatest_dist, node_distance_type const& d) { - return greatest_dist <= index::detail::cdist_value - ::template get(d); - } - - inline distance_predicates_type const& dist_pred() const - { - return nearest_predicate_access::get(m_pred).distance_predicates; + return greatest_dist <= d; } inline unsigned max_count() const @@ -624,6 +518,11 @@ private: return nearest_predicate_access::get(m_pred).count; } + nearest_predicate_type const& predicate() const + { + return nearest_predicate_access::get(m_pred); + } + const Translator * m_translator; Predicates m_pred; diff --git a/include/boost/geometry/index/predicates.hpp b/include/boost/geometry/index/predicates.hpp index 02fa6558f..5266621d8 100644 --- a/include/boost/geometry/index/predicates.hpp +++ b/include/boost/geometry/index/predicates.hpp @@ -211,8 +211,8 @@ inline detail::satisfies satisfies(UnaryPredicate const& pred) \brief Generate nearest() predicate. When nearest predicate is passed to the query, k-nearest neighbour search will be performed. - -The simplest way of defining the knn query is passing a \c Point to which \c Values must be closest. +\c nearest() predicate takes a \c Point from which distance to \c Values is calculated +and the maximum number of \c Values that should be returned. \par Example \verbatim @@ -235,6 +235,38 @@ nearest(Point const& point, unsigned k) return detail::nearest(point, k); } +#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL + +/*! +\brief Generate path() predicate. + +When path predicate is passed to the query, the returned values are k values on the path closest to +its begin. \c path() predicate takes a \c Linestring defining the path and the maximum +number of \c Values that should be returned. + +\par Example +\verbatim +bgi::query(spatial_index, bgi::path(pt, 5), std::back_inserter(result)); +bgi::query(spatial_index, bgi::path(pt, 5) && bgi::intersects(box), std::back_inserter(result)); +\endverbatim + +\warning +Only one distance predicate (\c nearest() or \c path()) may be used in a query. + +\ingroup predicates + +\param point The point from which distance is calculated. +\param k The maximum number of values to return. +*/ +template inline +detail::path +path(Linestring const& linestring, unsigned k) +{ + return detail::path(linestring, k); +} + +#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL + namespace detail { // operator! generators diff --git a/include/boost/geometry/index/rtree.hpp b/include/boost/geometry/index/rtree.hpp index 39fab6167..b3f8adcc3 100644 --- a/include/boost/geometry/index/rtree.hpp +++ b/include/boost/geometry/index/rtree.hpp @@ -733,11 +733,11 @@ public: if ( !m_members.root ) return 0; - static const unsigned nearest_count = detail::predicates_count_nearest::value; - static const bool is_nearest = 0 < nearest_count; - BOOST_MPL_ASSERT_MSG((nearest_count <= 1), PASS_ONLY_ONE_NEAREST_PREDICATE, (Predicates)); + static const unsigned distance_predicates_count = detail::predicates_count_distance::value; + static const bool is_distance_predicate = 0 < distance_predicates_count; + BOOST_MPL_ASSERT_MSG((distance_predicates_count <= 1), PASS_ONLY_ONE_DISTANCE_PREDICATE, (Predicates)); - return query_dispatch(predicates, out_it, boost::mpl::bool_()); + return query_dispatch(predicates, out_it, boost::mpl::bool_()); } #ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL @@ -762,24 +762,24 @@ public: template typename boost::mpl::if_c< - detail::predicates_count_nearest::value == 0, + detail::predicates_count_distance::value == 0, detail::rtree::spatial_query_iterator, - detail::rtree::nearest_query_iterator< + detail::rtree::distance_query_iterator< value_type, options_type, translator_type, box_type, allocators_type, Predicates, - detail::predicates_find_nearest::value + detail::predicates_find_distance::value > >::type qbegin(Predicates const& predicates) const { - static const unsigned nearest_count = detail::predicates_count_nearest::value; - BOOST_MPL_ASSERT_MSG((nearest_count <= 1), PASS_ONLY_ONE_NEAREST_PREDICATE, (Predicates)); + static const unsigned distance_predicates_count = detail::predicates_count_distance::value; + BOOST_MPL_ASSERT_MSG((distance_predicates_count <= 1), PASS_ONLY_ONE_DISTANCE_PREDICATE, (Predicates)); typedef typename boost::mpl::if_c< - detail::predicates_count_nearest::value == 0, + detail::predicates_count_distance::value == 0, detail::rtree::spatial_query_iterator, - detail::rtree::nearest_query_iterator< + detail::rtree::distance_query_iterator< value_type, options_type, translator_type, box_type, allocators_type, Predicates, - detail::predicates_find_nearest::value + detail::predicates_find_distance::value > >::type iterator_type; @@ -791,24 +791,24 @@ public: template typename boost::mpl::if_c< - detail::predicates_count_nearest::value == 0, + detail::predicates_count_distance::value == 0, detail::rtree::spatial_query_iterator, - detail::rtree::nearest_query_iterator< + detail::rtree::distance_query_iterator< value_type, options_type, translator_type, box_type, allocators_type, Predicates, - detail::predicates_find_nearest::value + detail::predicates_find_distance::value > >::type qend(Predicates const& predicates) const { - static const unsigned nearest_count = detail::predicates_count_nearest::value; - BOOST_MPL_ASSERT_MSG((nearest_count <= 1), PASS_ONLY_ONE_NEAREST_PREDICATE, (Predicates)); + static const unsigned distance_predicates_count = detail::predicates_count_distance::value; + BOOST_MPL_ASSERT_MSG((distance_predicates_count <= 1), PASS_ONLY_ONE_DISTANCE_PREDICATE, (Predicates)); typedef typename boost::mpl::if_c< - detail::predicates_count_nearest::value == 0, + detail::predicates_count_distance::value == 0, detail::rtree::spatial_query_iterator, - detail::rtree::nearest_query_iterator< + detail::rtree::distance_query_iterator< value_type, options_type, translator_type, box_type, allocators_type, Predicates, - detail::predicates_find_nearest::value + detail::predicates_find_distance::value > >::type iterator_type; @@ -1182,7 +1182,7 @@ private: strong */ template - size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_ const& /*is_nearest*/) const + size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_ const& /*is_distance_predicate*/) const { detail::rtree::visitors::spatial_query find_v(m_members.translator(), predicates, out_it); @@ -1199,37 +1199,23 @@ private: strong */ template - size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_ const& /*is_nearest*/) const + size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_ const& /*is_distance_predicate*/) const { - static const unsigned nearest_index = detail::predicates_find_nearest::value; - typedef index::detail::predicates_element nearest_predicate_access; - typedef typename index::detail::distance_predicates_type::type distance_predicates_type; - typedef typename detail::point_relation::type point_relation; - typedef typename detail::relation::value_type point_type; - - typedef detail::rtree::visitors::nearest_query_result_k< - value_type, - translator_type, - point_type, - OutIter - > result_type; - - result_type result(nearest_predicate_access::get(predicates).count, out_it); - - detail::rtree::visitors::nearest_query< + static const unsigned distance_predicate_index = detail::predicates_find_distance::value; + detail::rtree::visitors::distance_query< value_type, options_type, translator_type, box_type, allocators_type, Predicates, - nearest_index, - result_type - > nearest_v(m_members.parameters(), m_members.translator(), predicates, result); + distance_predicate_index, + OutIter + > distance_v(m_members.parameters(), m_members.translator(), predicates, out_it); - detail::rtree::apply_visitor(nearest_v, *m_members.root); + detail::rtree::apply_visitor(distance_v, *m_members.root); - return result.finish(); + return distance_v.finish(); } struct members_holder