geometry.index: introduced distance query - a generalized nearest query. distance calculation simplified. nearest query implemented using distance query. added path() predicate and query implemented using distance query as well.

[SVN r84209]
This commit is contained in:
Adam Wulkiewicz 2013-05-09 18:01:25 +00:00
parent c5b6130f30
commit 72e2ee5ade
6 changed files with 274 additions and 1043 deletions

View File

@ -15,35 +15,12 @@
#include <boost/geometry/index/detail/algorithms/comparable_distance_near.hpp>
#include <boost/geometry/index/detail/algorithms/comparable_distance_far.hpp>
#include <boost/geometry/index/detail/algorithms/comparable_distance_centroid.hpp>
#include <boost/geometry/index/detail/tuples.hpp>
#include <boost/geometry/index/detail/algorithms/path_intersection.hpp>
#include <boost/geometry/index/detail/tags.hpp>
// 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 <typename NearestPredicate>
struct distance_predicates_type
{
typedef void type;
};
template <typename DistancePredicates>
struct distance_predicates_type< detail::nearest<DistancePredicates> >
{
typedef DistancePredicates type;
};
// ------------------------------------------------------------------ //
// relations
// ------------------------------------------------------------------ //
@ -116,766 +93,66 @@ struct relation< to_furthest<T> >
};
// ------------------------------------------------------------------ //
// distance predicates
// calculate_distance
// ------------------------------------------------------------------ //
//template <typename PointRelation>
//struct unbounded
// : nonassignable
//{
// inline explicit unbounded(PointRelation const& pr)
// : point_relation(pr)
// {}
//
// PointRelation point_relation;
//};
//
//template <typename PointRelation, typename MinRelation>
//struct min_bounded
// : nonassignable
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename geometry::default_distance_result<point_type, point_type>::type distance_type;
//
// inline min_bounded(PointRelation const& pr, MinRelation const& min_rel)
// : point_relation(pr)
// , comparable_min(
// relation<MinRelation>::value(min_rel) *
// relation<MinRelation>::value(min_rel) )
// {}
//
// PointRelation point_relation;
// distance_type comparable_min;
//};
//
//template <typename PointRelation, typename MaxRelation>
//struct max_bounded
// : nonassignable
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename geometry::default_distance_result<point_type, point_type>::type distance_type;
//
// inline max_bounded(PointRelation const& pr, MaxRelation const& max_rel)
// : point_relation(pr)
// , comparable_max(
// relation<MaxRelation>::value(max_rel) *
// relation<MaxRelation>::value(max_rel) )
// {}
//
// PointRelation point_relation;
// distance_type comparable_max;
//};
//
//template <typename PointRelation, typename MinRelation, typename MaxRelation>
//struct bounded
// : nonassignable
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename geometry::default_distance_result<point_type, point_type>::type distance_type;
//
// inline bounded(PointRelation const& pr, MinRelation const& min_rel, MaxRelation const& max_rel)
// : point_relation(pr)
// , comparable_min(
// relation<MinRelation>::value(min_rel) *
// relation<MinRelation>::value(min_rel) )
// , comparable_max(
// relation<MaxRelation>::value(max_rel) *
// relation<MaxRelation>::value(max_rel) )
// {}
//
// PointRelation point_relation;
// distance_type comparable_min;
// distance_type comparable_max;
//};
// ------------------------------------------------------------------ //
// point_relation trait
// ------------------------------------------------------------------ //
template <typename PointRelation>
struct point_relation
template <typename Predicate, typename Indexable, typename Tag>
struct calculate_distance
{
typedef PointRelation type;
BOOST_MPL_ASSERT_MSG((false), INVALID_PREDICATE_OR_TAG, (calculate_distance));
};
//template <typename PointRelation>
//struct point_relation< detail::unbounded<PointRelation> >
//{
// typedef PointRelation type;
//};
//
//template <typename PointRelation, typename MinRelation>
//struct point_relation< detail::min_bounded<PointRelation, MinRelation> >
//{
// typedef PointRelation type;
//};
//
//template <typename PointRelation, typename MaxRelation>
//struct point_relation< detail::max_bounded<PointRelation, MaxRelation> >
//{
// typedef PointRelation type;
//};
//
//template <typename PointRelation, typename MinRelation, typename MaxRelation>
//struct point_relation< detail::bounded<PointRelation, MinRelation, MaxRelation> >
//{
// typedef PointRelation type;
//};
// ------------------------------------------------------------------ //
// helpers
// ------------------------------------------------------------------ //
// algorithms
// cdist
template <typename T, typename Tag>
struct cdist
{
T value;
};
// cdist_merge
template <typename CDistTuple, typename CDist>
struct cdist_merge
{
typedef typename detail::tuples::add_unique<
CDistTuple,
CDist
>::type type;
};
template <typename T, typename Tag, typename OtherTag>
struct cdist_merge<
cdist<T, Tag>,
cdist<T, OtherTag> >
{
typedef boost::tuple<
cdist<T, Tag>,
cdist<T, OtherTag>
> type;
};
template <typename T, typename Tag>
struct cdist_merge<
cdist<T, Tag>,
cdist<T, Tag> >
{
typedef cdist<T, Tag> type;
};
// cdist_value_type
template <typename CDistTuple>
struct cdist_value
{
typedef typename cdist_value<
typename boost::tuples::element<0, CDistTuple>::type
>::type type;
template <typename Tag>
static inline type & get(CDistTuple & cdtup)
{
return boost::get<
tuples::find_index<
CDistTuple,
cdist<type, Tag>
>::value
>(cdtup).value;
}
template <typename Tag>
static inline type const& get(CDistTuple const& cdtup)
{
return boost::get<
tuples::find_index<
CDistTuple,
cdist<type, Tag>
>::value
>(cdtup).value;
}
};
template <typename T, typename Tag>
struct cdist_value<
cdist<T, Tag>
>
{
typedef T type;
template <typename Tag2>
static inline type & get(cdist<T, Tag> & cd)
{
BOOST_MPL_ASSERT_MSG(
(boost::is_same< cdist<T, Tag2>, cdist<T, Tag> >::value),
TAGS_DO_NOT_MATCH,
(cdist_value));
return cd.value;
}
template <typename Tag2>
static inline type const& get(cdist<T, Tag> const& cd)
{
BOOST_MPL_ASSERT_MSG(
(boost::is_same< cdist<T, Tag2>, cdist<T, Tag> >::value),
TAGS_DO_NOT_MATCH,
(cdist_value));
return cd.value;
}
};
// distances_calc_impl_rel
template <typename RelDist>
struct distances_calc_impl_rel
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_RELATION,
(distances_calc_impl_rel));
};
template <typename T>
struct distances_calc_impl_rel<
cdist<T, detail::to_nearest_tag>
>
{
template <typename Point, typename Indexable>
typename geometry::default_distance_result<Point, Indexable>::type
static inline apply(Point const& p, Indexable const& i)
{
return index::detail::comparable_distance_near(p, i);
}
};
template <typename T>
struct distances_calc_impl_rel<
cdist<T, detail::to_centroid_tag>
>
{
template <typename Point, typename Indexable>
typename geometry::default_distance_result<Point, Indexable>::type
static inline apply(Point const& p, Indexable const& i)
{
return index::detail::comparable_distance_centroid(p, i);
}
};
template <typename T>
struct distances_calc_impl_rel<
cdist<T, detail::to_furthest_tag>
>
{
template <typename Point, typename Indexable>
typename geometry::default_distance_result<Point, Indexable>::type
static inline apply(Point const& p, Indexable const& i)
{
return index::detail::comparable_distance_far(p, i);
}
};
// distances_calc_impl_tuple
template <typename Distances, typename Point, typename Indexable, unsigned N>
struct distances_calc_impl_tuple
{
// TODO MPL ASSERT 0 < N
static inline void apply(Distances & d, Point const& p, Indexable const&i)
{
boost::get<N - 1>(d).value =
distances_calc_impl_rel<
typename boost::tuples::element<N - 1, Distances>::type
>::apply(p, i);
distances_calc_impl_tuple<
Distances,
Point,
Indexable,
N - 1
>::apply(d, p, i);
}
};
template <typename Distances, typename Point, typename Indexable>
struct distances_calc_impl_tuple<Distances, Point, Indexable, 1>
{
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 <typename Distances, typename Point, typename Indexable>
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<Distances>::value
>::apply(d, p, i);
}
};
template <typename T, typename Tag, typename Point, typename Indexable>
struct distances_calc_impl<
cdist<T, Tag>,
Point,
Indexable
>
{
static inline void apply(cdist<T, Tag> & d, Point const& p, Indexable const&i)
{
d.value = distances_calc_impl_rel<
cdist<T, Tag>
>::apply(p, i);
}
};
// ------------------------------------------------------------------ //
// distance_calc and distances_predicates_check
// ------------------------------------------------------------------ //
// this handles nearest() with default Point parameter, to_nearest() and bounds
template <typename PointRelation, typename Indexable, typename Tag>
struct distances_calc
struct calculate_distance< nearest<PointRelation>, Indexable, Tag >
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_TAG,
(distances_calc));
};
typedef detail::relation<PointRelation> relation;
typedef typename relation::value_type point_type;
typedef typename geometry::default_distance_result<point_type, Indexable>::type result_type;
template <typename PointRelation, typename Indexable, typename Tag>
struct distances_predicates_check
{
BOOST_MPL_ASSERT_MSG(
(false),
NOT_IMPLEMENTED_FOR_THIS_TAG,
(distances_predicates_check));
};
// ------------------------------------------------------------------ //
// distance_calc for value_tag
// ------------------------------------------------------------------ //
template <typename PointRelation, typename Indexable>
struct distances_calc<PointRelation, Indexable, value_tag>
{
typedef typename detail::relation<PointRelation>::value_type point_type;
typedef typename detail::relation<PointRelation>::tag point_relation_tag;
typedef typename geometry::default_distance_result<point_type, Indexable>::type distance_type;
typedef detail::cdist<distance_type, point_relation_tag> result_type;
static inline result_type apply(PointRelation const& p, Indexable const& i)
{
result_type res;
distances_calc_impl<result_type, point_type, Indexable>
::apply(res, relation<PointRelation>::value(p), i);
return res;
}
};
//template <typename PointRelation, typename Indexable>
//struct distances_calc<
// detail::unbounded<PointRelation>,
// Indexable,
// value_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename detail::relation<PointRelation>::tag point_relation_tag;
// typedef typename geometry::default_distance_result<point_type, Indexable>::type distance_type;
//
// typedef detail::cdist<distance_type, point_relation_tag> result_type;
//
// static inline result_type apply(detail::unbounded<PointRelation> const& pp, Indexable const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Indexable>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename Indexable>
//struct distances_calc<
// detail::min_bounded<PointRelation, MinRelation>,
// Indexable,
// value_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename detail::relation<PointRelation>::tag point_relation_tag;
// typedef typename geometry::default_distance_result<point_type, Indexable>::type distance_type;
// typedef typename detail::relation<MinRelation>::tag min_relation_tag;
//
// typedef typename detail::cdist_merge<
// cdist<distance_type, point_relation_tag>,
// cdist<distance_type, min_relation_tag>
// >::type result_type;
//
// static inline result_type apply(detail::min_bounded<PointRelation, MinRelation> const& pp, Indexable const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Indexable>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
//
//template <typename PointRelation, typename MaxRelation, typename Indexable>
//struct distances_calc<
// detail::max_bounded<PointRelation, MaxRelation>,
// Indexable,
// value_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename detail::relation<PointRelation>::tag point_relation_tag;
// typedef typename geometry::default_distance_result<point_type, Indexable>::type distance_type;
// typedef typename detail::relation<MaxRelation>::tag max_relation_tag;
//
// typedef typename detail::cdist_merge<
// cdist<distance_type, point_relation_tag>,
// cdist<distance_type, max_relation_tag>
// >::type result_type;
//
// static inline result_type apply(detail::max_bounded<PointRelation, MaxRelation> const& pp, Indexable const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Indexable>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename MaxRelation, typename Indexable>
//struct distances_calc<
// detail::bounded<PointRelation, MinRelation, MaxRelation>,
// Indexable,
// value_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename detail::relation<PointRelation>::tag point_relation_tag;
// typedef typename geometry::default_distance_result<point_type, Indexable>::type distance_type;
// typedef typename detail::relation<MinRelation>::tag min_relation_tag;
// typedef typename detail::relation<MaxRelation>::tag max_relation_tag;
//
// typedef typename detail::cdist_merge<
// typename detail::cdist_merge<
// cdist<distance_type, point_relation_tag>,
// cdist<distance_type, min_relation_tag>
// >::type,
// cdist<distance_type, max_relation_tag>
// >::type result_type;
//
// static inline result_type apply(
// detail::bounded<PointRelation, MinRelation, MaxRelation> const& pp,
// Indexable const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Indexable>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
// ------------------------------------------------------------------ //
// distance_predicates_check for value_tag
// ------------------------------------------------------------------ //
template <typename PointRelation, typename Indexable>
struct distances_predicates_check<PointRelation, Indexable, value_tag>
{
template <typename Distances>
static inline bool apply(PointRelation const&, Distances const&)
static inline bool apply(nearest<PointRelation> const& p, Indexable const& i, result_type & result)
{
result = index::detail::comparable_distance_near(relation::value(p.point_or_relation), i);
return true;
}
};
//template <typename PointRelation, typename Indexable>
//struct distances_predicates_check<
// detail::unbounded<PointRelation>,
// Indexable,
// value_tag
//>
//{
// template <typename Distances>
// static inline bool apply(detail::unbounded<PointRelation> const&, Distances const&)
// {
// return true;
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename Indexable>
//struct distances_predicates_check<
// detail::min_bounded<PointRelation, MinRelation>,
// Indexable,
// value_tag
//>
//{
// typedef typename detail::relation<MinRelation>::tag min_relation_tag;
//
// template <typename Distances>
// static inline bool apply(
// detail::min_bounded<PointRelation, MinRelation> const& pred,
// Distances const& d)
// {
// return pred.comparable_min <=
// detail::cdist_value<Distances>::template get<min_relation_tag>(d);
// }
//};
//
//template <typename PointRelation, typename MaxRelation, typename Indexable>
//struct distances_predicates_check<
// detail::max_bounded<PointRelation, MaxRelation>,
// Indexable,
// value_tag
//>
//{
// typedef typename detail::relation<MaxRelation>::tag max_relation_tag;
//
// template <typename Distances>
// static inline bool apply(
// detail::max_bounded<PointRelation, MaxRelation> const& pred,
// Distances const& d)
// {
// return pred.comparable_max <=
// detail::cdist_value<Distances>::template get<max_relation_tag>(d);
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename MaxRelation, typename Indexable>
//struct distances_predicates_check<
// detail::bounded<PointRelation, MinRelation, MaxRelation>,
// Indexable,
// value_tag
//>
//{
// typedef typename detail::relation<MinRelation>::tag min_relation_tag;
// typedef typename detail::relation<MaxRelation>::tag max_relation_tag;
//
// template <typename Distances>
// static inline bool apply(
// detail::bounded<PointRelation, MinRelation, MaxRelation> const& pred,
// Distances const& d)
// {
// return pred.comparable_min
// <= detail::cdist_value<Distances>::template get<min_relation_tag>(d)
// && detail::cdist_value<Distances>::template get<max_relation_tag>(d)
// <= pred.comparable_max;
// }
//};
// ------------------------------------------------------------------ //
// distance_calc for bounds_tag
// ------------------------------------------------------------------ //
template <typename PointRelation, typename Box>
struct distances_calc<
PointRelation,
Box,
bounds_tag>
template <typename Point, typename Indexable>
struct calculate_distance< nearest< to_centroid<Point> >, Indexable, value_tag>
{
typedef typename detail::relation<PointRelation>::value_type point_type;
typedef typename geometry::default_distance_result<point_type, Box>::type distance_type;
typedef Point point_type;
typedef typename geometry::default_distance_result<point_type, Indexable>::type result_type;
typedef detail::cdist<distance_type, detail::to_nearest_tag> result_type;
static inline result_type apply(PointRelation const& p, Box const& i)
{
result_type res;
distances_calc_impl<result_type, point_type, Box>
::apply(res, relation<PointRelation>::value(p), i);
return res;
}
};
//template <typename PointRelation, typename Box>
//struct distances_calc<
// detail::unbounded<PointRelation>,
// Box,
// bounds_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename geometry::default_distance_result<point_type, Box>::type distance_type;
//
// typedef detail::cdist<distance_type, detail::to_nearest_tag> result_type;
//
// static inline result_type apply(detail::unbounded<PointRelation> const& pp, Box const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Box>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename Box>
//struct distances_calc<
// detail::min_bounded<PointRelation, MinRelation>,
// Box,
// bounds_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename geometry::default_distance_result<point_type, Box>::type distance_type;
//
// typedef typename detail::cdist_merge<
// cdist<distance_type, detail::to_nearest_tag>,
// cdist<distance_type, detail::to_furthest_tag>
// >::type result_type;
//
// static inline result_type apply(detail::min_bounded<PointRelation, MinRelation> const& pp, Box const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Box>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
//
//template <typename PointRelation, typename MaxRelation, typename Box>
//struct distances_calc<
// detail::max_bounded<PointRelation, MaxRelation>,
// Box,
// bounds_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename geometry::default_distance_result<point_type, Box>::type distance_type;
//
// typedef cdist<distance_type, detail::to_nearest_tag> result_type;
//
// static inline result_type apply(detail::max_bounded<PointRelation, MaxRelation> const& pp, Box const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Box>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename MaxRelation, typename Box>
//struct distances_calc<
// detail::bounded<PointRelation, MinRelation, MaxRelation>,
// Box,
// bounds_tag
//>
//{
// typedef typename detail::relation<PointRelation>::value_type point_type;
// typedef typename geometry::default_distance_result<point_type, Box>::type distance_type;
//
// typedef typename detail::cdist_merge<
// cdist<distance_type, detail::to_nearest_tag>,
// cdist<distance_type, detail::to_furthest_tag>
// >::type result_type;
//
// static inline result_type apply(detail::bounded<PointRelation, MinRelation, MaxRelation> const& pp, Box const& i)
// {
// result_type res;
// distances_calc_impl<result_type, point_type, Box>
// ::apply(res, relation<PointRelation>::value(pp.point_relation), i);
// return res;
// }
//};
// ------------------------------------------------------------------ //
// distance_predicates_check for bounds_tag
// ------------------------------------------------------------------ //
template <typename PointRelation, typename Box>
struct distances_predicates_check<
PointRelation,
Box,
bounds_tag>
{
template <typename Distances>
static inline bool apply(PointRelation const&, Distances const&)
static inline bool apply(nearest< to_centroid<Point> > const& p, Indexable const& i, result_type & result)
{
result = index::detail::comparable_distance_centroid(p.point_or_relation.value, i);
return true;
}
};
//template <typename PointRelation, typename Box>
//struct distances_predicates_check<
// detail::unbounded<PointRelation>,
// Box,
// bounds_tag>
//{
// template <typename Distances>
// static inline bool apply(
// detail::unbounded<PointRelation> const&,
// Distances const&)
// {
// return true;
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename Box>
//struct distances_predicates_check<
// detail::min_bounded<PointRelation, MinRelation>,
// Box,
// bounds_tag>
//{
// template <typename Distances>
// static inline bool apply(
// detail::min_bounded<PointRelation, MinRelation> const& pred,
// Distances const& d)
// {
// return pred.comparable_min
// <= cdist_value<Distances>::template get<detail::to_furthest_tag>(d);
// }
//};
//
//template <typename PointRelation, typename MaxRelation, typename Box>
//struct distances_predicates_check<
// detail::max_bounded<PointRelation, MaxRelation>,
// Box,
// bounds_tag>
//{
// template <typename Distances>
// static inline bool apply(
// detail::max_bounded<PointRelation, MaxRelation> const& pred,
// Distances const& d)
// {
// return cdist_value<Distances>::template get<detail::to_nearest_tag>(d)
// <= pred.comparable_max;
// }
//};
//
//template <typename PointRelation, typename MinRelation, typename MaxRelation, typename Box>
//struct distances_predicates_check<
// detail::bounded<PointRelation, MinRelation, MaxRelation>,
// Box,
// bounds_tag>
//{
// template <typename Distances>
// static inline bool apply(
// detail::bounded<PointRelation, MinRelation, MaxRelation> const& pred,
// Distances const& d)
// {
// return pred.comparable_min
// <= cdist_value<Distances>::template get<detail::to_furthest_tag>(d)
// && cdist_value<Distances>::template get<detail::to_nearest_tag>(d)
// <= pred.comparable_max;
// }
//};
template <typename Point, typename Indexable>
struct calculate_distance< nearest< to_furthest<Point> >, Indexable, value_tag>
{
typedef Point point_type;
typedef typename geometry::default_distance_result<point_type, Indexable>::type result_type;
static inline bool apply(nearest< to_furthest<Point> > const& p, Indexable const& i, result_type & result)
{
result = index::detail::comparable_distance_far(p.point_or_relation.value, i);
return true;
}
};
template <typename Linestring, typename Indexable, typename Tag>
struct calculate_distance< path<Linestring>, Indexable, Tag>
{
typedef typename geometry::default_length_result<Linestring>::type result_type;
static inline bool apply(path<Linestring> const& p, Indexable const& i, result_type & result)
{
return index::detail::path_intersection(i, p.linestring, result);
}
};
}}}} // namespace boost::geometry::index::detail

View File

@ -129,14 +129,25 @@ struct not_within
Geometry geometry;
};
template <typename DistancePredicates>
template <typename PointOrRelation>
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 <typename Linestring>
struct path
{
path(Linestring const& ls, unsigned k)
: linestring(ls)
, count(k)
{}
Linestring linestring;
unsigned count;
};
@ -377,6 +388,16 @@ struct predicate_check<nearest<DistancePredicates>, value_tag>
}
};
template <typename Linestring>
struct predicate_check<path<Linestring>, value_tag>
{
template <typename Value, typename Box>
static inline bool apply(path<Linestring> const&, Value const&, Box const&)
{
return true;
}
};
// ------------------------------------------------------------------ //
// predicate_check_default for bounds
// ------------------------------------------------------------------ //
@ -571,6 +592,16 @@ struct predicate_check<nearest<DistancePredicates>, bounds_tag>
}
};
template <typename Linestring>
struct predicate_check<path<Linestring>, bounds_tag>
{
template <typename Value, typename Box>
static inline bool apply(path<Linestring> 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 <typename P>
struct predicates_is_nearest
struct predicates_is_distance
{
static const unsigned value = 0;
};
template <typename DistancePredicates>
struct predicates_is_nearest< nearest<DistancePredicates> >
struct predicates_is_distance< nearest<DistancePredicates> >
{
static const unsigned value = 1;
};
template <typename Linestring>
struct predicates_is_distance< path<Linestring> >
{
static const unsigned value = 1;
};
@ -819,46 +856,46 @@ struct predicates_is_nearest< nearest<DistancePredicates> >
// predicates_count_nearest
template <typename T>
struct predicates_count_nearest
struct predicates_count_distance
{
static const unsigned value = predicates_is_nearest<T>::value;
static const unsigned value = predicates_is_distance<T>::value;
};
//template <typename F, typename S>
//struct predicates_count_nearest< std::pair<F, S> >
//struct predicates_count_distance< std::pair<F, S> >
//{
// static const unsigned value = predicates_is_nearest<F>::value
// + predicates_is_nearest<S>::value;
// static const unsigned value = predicates_is_distance<F>::value
// + predicates_is_distance<S>::value;
//};
template <typename Tuple, unsigned N>
struct predicates_count_nearest_tuple
struct predicates_count_distance_tuple
{
static const unsigned value =
predicates_is_nearest<typename boost::tuples::element<N-1, Tuple>::type>::value
+ predicates_count_nearest_tuple<Tuple, N-1>::value;
predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value
+ predicates_count_distance_tuple<Tuple, N-1>::value;
};
template <typename Tuple>
struct predicates_count_nearest_tuple<Tuple, 1>
struct predicates_count_distance_tuple<Tuple, 1>
{
static const unsigned value =
predicates_is_nearest<typename boost::tuples::element<0, Tuple>::type>::value;
predicates_is_distance<typename boost::tuples::element<0, Tuple>::type>::value;
};
//template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
//struct predicates_count_nearest< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
//struct predicates_count_distance< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
//{
// static const unsigned value = predicates_count_nearest_tuple<
// static const unsigned value = predicates_count_distance_tuple<
// boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,
// boost::tuples::length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::value
// >::value;
//};
template <typename Head, typename Tail>
struct predicates_count_nearest< boost::tuples::cons<Head, Tail> >
struct predicates_count_distance< boost::tuples::cons<Head, Tail> >
{
static const unsigned value = predicates_count_nearest_tuple<
static const unsigned value = predicates_count_distance_tuple<
boost::tuples::cons<Head, Tail>,
boost::tuples::length< boost::tuples::cons<Head, Tail> >::value
>::value;
@ -867,50 +904,50 @@ struct predicates_count_nearest< boost::tuples::cons<Head, Tail> >
// predicates_find_nearest
template <typename T>
struct predicates_find_nearest
struct predicates_find_distance
{
static const unsigned value = predicates_is_nearest<T>::value ? 0 : 1;
static const unsigned value = predicates_is_distance<T>::value ? 0 : 1;
};
//template <typename F, typename S>
//struct predicates_find_nearest< std::pair<F, S> >
//struct predicates_find_distance< std::pair<F, S> >
//{
// static const unsigned value = predicates_is_nearest<F>::value ? 0 :
// (predicates_is_nearest<S>::value ? 1 : 2);
// static const unsigned value = predicates_is_distance<F>::value ? 0 :
// (predicates_is_distance<S>::value ? 1 : 2);
//};
template <typename Tuple, unsigned N>
struct predicates_find_nearest_tuple
struct predicates_find_distance_tuple
{
static const bool is_found = predicates_find_nearest_tuple<Tuple, N-1>::is_found
|| predicates_is_nearest<typename boost::tuples::element<N-1, Tuple>::type>::value;
static const bool is_found = predicates_find_distance_tuple<Tuple, N-1>::is_found
|| predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value;
static const unsigned value = predicates_find_nearest_tuple<Tuple, N-1>::is_found ?
predicates_find_nearest_tuple<Tuple, N-1>::value :
(predicates_is_nearest<typename boost::tuples::element<N-1, Tuple>::type>::value ?
static const unsigned value = predicates_find_distance_tuple<Tuple, N-1>::is_found ?
predicates_find_distance_tuple<Tuple, N-1>::value :
(predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value ?
N-1 : boost::tuples::length<Tuple>::value);
};
template <typename Tuple>
struct predicates_find_nearest_tuple<Tuple, 1>
struct predicates_find_distance_tuple<Tuple, 1>
{
static const bool is_found = predicates_is_nearest<typename boost::tuples::element<0, Tuple>::type>::value;
static const bool is_found = predicates_is_distance<typename boost::tuples::element<0, Tuple>::type>::value;
static const unsigned value = is_found ? 0 : boost::tuples::length<Tuple>::value;
};
//template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
//struct predicates_find_nearest< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
//struct predicates_find_distance< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
//{
// static const unsigned value = predicates_find_nearest_tuple<
// static const unsigned value = predicates_find_distance_tuple<
// boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,
// boost::tuples::length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::value
// >::value;
//};
template <typename Head, typename Tail>
struct predicates_find_nearest< boost::tuples::cons<Head, Tail> >
struct predicates_find_distance< boost::tuples::cons<Head, Tail> >
{
static const unsigned value = predicates_find_nearest_tuple<
static const unsigned value = predicates_find_distance_tuple<
boost::tuples::cons<Head, Tail>,
boost::tuples::length< boost::tuples::cons<Head, Tail> >::value
>::value;

View File

@ -143,9 +143,9 @@ private:
};
template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates, unsigned NearestPredicateIndex>
class nearest_query_iterator
class distance_query_iterator
{
typedef visitors::nearest_query_incremental<Value, Options, Translator, Box, Allocators, Predicates, NearestPredicateIndex> visitor_type;
typedef visitors::distance_query_incremental<Value, Options, Translator, Box, Allocators, Predicates, NearestPredicateIndex> 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<Value, Allocators>)
friend bool operator==(distance_query_iterator const& l, end_query_iterator<Value, Allocators>)
{
return l.m_visitor.is_end();
}
friend bool operator==(end_query_iterator<Value, Allocators>, nearest_query_iterator const& r)
friend bool operator==(end_query_iterator<Value, Allocators>, 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<Value, Allocators>)
friend bool operator!=(distance_query_iterator const& l, end_query_iterator<Value, Allocators>)
{
return !l.m_visitor.is_end();
}
friend bool operator!=(end_query_iterator<Value, Allocators>, nearest_query_iterator const& r)
friend bool operator!=(end_query_iterator<Value, Allocators>, distance_query_iterator const& r)
{
return !r.m_visitor.is_end();
}

View File

@ -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 <typename Value, typename Translator, typename Point>
//struct nearest_query_result_one
//{
//public:
// typedef typename geometry::default_distance_result<
// Point,
// typename translator::indexable_type<Translator>::type
// >::type distance_type;
//
// inline nearest_query_result_one(Value & value)
// : m_value(value)
// , m_comp_dist((std::numeric_limits<distance_type>::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<distance_type>::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 <typename Value, typename Translator, typename Point, typename OutIt>
class nearest_query_result_k
template <typename Value, typename Translator, typename DistanceType, typename OutIt>
class distance_query_result
{
public:
typedef typename geometry::default_distance_result<
Point,
typename indexable_type<Translator>::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<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
public:
@ -159,31 +109,21 @@ public:
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
typedef index::detail::predicates_element<NearestPredicateIndex, Predicates> nearest_predicate_access;
typedef typename index::detail::distance_predicates_type<typename nearest_predicate_access::type>::type distance_predicates_type;
typedef index::detail::predicates_element<DistancePredicateIndex, Predicates> nearest_predicate_access;
typedef typename nearest_predicate_access::type nearest_predicate_type;
typedef typename indexable_type<Translator>::type indexable_type;
typedef index::detail::distances_calc<distance_predicates_type, Box, index::detail::bounds_tag> node_distances_calc;
typedef typename node_distances_calc::result_type node_distances_type;
typedef index::detail::distances_predicates_check<distance_predicates_type, Box, index::detail::bounds_tag> node_distances_predicates_check;
typedef index::detail::distances_calc<
distance_predicates_type,
typename indexable_type<Translator>::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<Translator>::type,
index::detail::value_tag
> value_distances_predicates_check;
typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, value_tag> calculate_value_distance;
typedef index::detail::calculate_distance<nearest_predicate_type, Box, bounds_tag> 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<Predicates>::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<node_distances_type, typename Allocators::node_pointer>
std::pair<node_distance_type, typename Allocators::node_pointer>
>::type active_branch_list_type;
active_branch_list_type active_branch_list;
@ -210,25 +150,22 @@ public:
if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(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<index::detail::value_tag, 0, predicates_len>(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<distance_predicates_type>::type point_relation_type;
typedef typename index::detail::relation<point_relation_type>::tag point_relation_tag;
// store value
m_result.store(
*it,
index::detail::cdist_value<value_distances_type>
::template get<point_relation_tag>(distances)
);
m_result.store(*it, value_distance);
}
}
}
}
inline size_t finish()
{
return m_result.finish();
}
private:
static inline bool abl_less(
std::pair<node_distances_type, typename Allocators::node_pointer> const& p1,
std::pair<node_distances_type, typename Allocators::node_pointer> const& p2)
std::pair<node_distance_type, typename Allocators::node_pointer> const& p1,
std::pair<node_distance_type, typename Allocators::node_pointer> const& p2)
{
return index::detail::cdist_value<node_distances_type>
::template get<index::detail::to_nearest_tag>(p1.first)
< index::detail::cdist_value<node_distances_type>
::template get<index::detail::to_nearest_tag>(p2.first);
return p1.first < p2.first;
}
template <typename Distance>
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<node_distances_type>
::template get<index::detail::to_nearest_tag>(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<Value, Translator, value_distance_type, OutIter> 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<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
{
public:
@ -337,31 +263,14 @@ public:
typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
typedef index::detail::predicates_element<NearestPredicateIndex, Predicates> nearest_predicate_access;
typedef typename index::detail::distance_predicates_type<typename nearest_predicate_access::type>::type distance_predicates_type;
typedef typename geometry::default_distance_result<
typename index::detail::relation<
typename index::detail::point_relation<distance_predicates_type>::type
>::value_type,
typename indexable_type<Translator>::type
>::type value_distance_type;
typedef index::detail::distances_calc<distance_predicates_type, Box, index::detail::bounds_tag> node_distances_calc;
typedef typename node_distances_calc::result_type node_distances_type;
typedef index::detail::distances_predicates_check<distance_predicates_type, Box, index::detail::bounds_tag> node_distances_predicates_check;
typedef typename index::detail::cdist_value<node_distances_type>::type node_distance_type;
typedef index::detail::distances_calc<
distance_predicates_type,
typename indexable_type<Translator>::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<Translator>::type,
index::detail::value_tag
> value_distances_predicates_check;
typedef index::detail::predicates_element<DistancePredicateIndex, Predicates> nearest_predicate_access;
typedef typename nearest_predicate_access::type nearest_predicate_type;
typedef typename indexable_type<Translator>::type indexable_type;
typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, value_tag> calculate_value_distance;
typedef index::detail::calculate_distance<nearest_predicate_type, Box, bounds_tag> 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<leaf>::type leaf_elements;
typedef std::pair<node_distances_type, node_pointer> branch_data;
typedef std::pair<node_distance_type, node_pointer> 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_element> 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<size_type>::max)())
@ -475,7 +384,7 @@ public:
return (std::numeric_limits<size_type>::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<size_type>::max)() == l.current_neighbor ||
@ -503,21 +412,22 @@ public:
if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(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<index::detail::value_tag, 0, predicates_len>(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<distance_predicates_type>::type point_relation_type;
typedef typename index::detail::relation<point_relation_type>::tag point_relation_tag;
// store value if it's closer than the furthest neighbour
value_distance_type dist = index::detail::cdist_value<value_distances_type>
::template get<point_relation_tag>(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<node_distances_type, typename Allocators::node_pointer> const& p1,
std::pair<node_distances_type, typename Allocators::node_pointer> const& p2)
static inline bool abl_less(std::pair<node_distance_type, typename Allocators::node_pointer> const& p1,
std::pair<node_distance_type, typename Allocators::node_pointer> const& p2)
{
return index::detail::cdist_value<node_distances_type>::template get<index::detail::to_nearest_tag>(p1.first)
< index::detail::cdist_value<node_distances_type>::template get<index::detail::to_nearest_tag>(p2.first);
return p1.first < p2.first;
}
static inline bool neighbors_less(std::pair<value_distance_type, const Value *> const& p1,
@ -599,8 +500,7 @@ private:
if ( first->branches.size() <= first->current_branch )
continue;
node_distance_type curr_dist = index::detail::cdist_value<node_distances_type>
::template get<index::detail::to_nearest_tag>(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 <typename Distance>
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<node_distances_type>
::template get<index::detail::to_nearest_tag>(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;

View File

@ -211,8 +211,8 @@ inline detail::satisfies<UnaryPredicate> 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>(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 <typename Linestring> inline
detail::path<Linestring>
path(Linestring const& linestring, unsigned k)
{
return detail::path<Linestring>(linestring, k);
}
#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
namespace detail {
// operator! generators

View File

@ -733,11 +733,11 @@ public:
if ( !m_members.root )
return 0;
static const unsigned nearest_count = detail::predicates_count_nearest<Predicates>::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<Predicates>::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_<is_nearest>());
return query_dispatch(predicates, out_it, boost::mpl::bool_<is_distance_predicate>());
}
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
@ -762,24 +762,24 @@ public:
template <typename Predicates>
typename boost::mpl::if_c<
detail::predicates_count_nearest<Predicates>::value == 0,
detail::predicates_count_distance<Predicates>::value == 0,
detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
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<Predicates>::value
detail::predicates_find_distance<Predicates>::value
>
>::type
qbegin(Predicates const& predicates) const
{
static const unsigned nearest_count = detail::predicates_count_nearest<Predicates>::value;
BOOST_MPL_ASSERT_MSG((nearest_count <= 1), PASS_ONLY_ONE_NEAREST_PREDICATE, (Predicates));
static const unsigned distance_predicates_count = detail::predicates_count_distance<Predicates>::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<Predicates>::value == 0,
detail::predicates_count_distance<Predicates>::value == 0,
detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
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<Predicates>::value
detail::predicates_find_distance<Predicates>::value
>
>::type iterator_type;
@ -791,24 +791,24 @@ public:
template <typename Predicates>
typename boost::mpl::if_c<
detail::predicates_count_nearest<Predicates>::value == 0,
detail::predicates_count_distance<Predicates>::value == 0,
detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
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<Predicates>::value
detail::predicates_find_distance<Predicates>::value
>
>::type
qend(Predicates const& predicates) const
{
static const unsigned nearest_count = detail::predicates_count_nearest<Predicates>::value;
BOOST_MPL_ASSERT_MSG((nearest_count <= 1), PASS_ONLY_ONE_NEAREST_PREDICATE, (Predicates));
static const unsigned distance_predicates_count = detail::predicates_count_distance<Predicates>::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<Predicates>::value == 0,
detail::predicates_count_distance<Predicates>::value == 0,
detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
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<Predicates>::value
detail::predicates_find_distance<Predicates>::value
>
>::type iterator_type;
@ -1182,7 +1182,7 @@ private:
strong
*/
template <typename Predicates, typename OutIter>
size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_<false> const& /*is_nearest*/) const
size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_<false> const& /*is_distance_predicate*/) const
{
detail::rtree::visitors::spatial_query<value_type, options_type, translator_type, box_type, allocators_type, Predicates, OutIter>
find_v(m_members.translator(), predicates, out_it);
@ -1199,37 +1199,23 @@ private:
strong
*/
template <typename Predicates, typename OutIter>
size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_<true> const& /*is_nearest*/) const
size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_<true> const& /*is_distance_predicate*/) const
{
static const unsigned nearest_index = detail::predicates_find_nearest<Predicates>::value;
typedef index::detail::predicates_element<nearest_index, Predicates> nearest_predicate_access;
typedef typename index::detail::distance_predicates_type<typename nearest_predicate_access::type >::type distance_predicates_type;
typedef typename detail::point_relation<distance_predicates_type>::type point_relation;
typedef typename detail::relation<point_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<Predicates>::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