[algorithms][distance] modify the various classes to do not inherit

from closest feature classes, but rather call their public (instead
of protected) interface; optimize the computation of comparable
distances by not re-computing them from closest features
This commit is contained in:
Menelaos Karavelas
2014-10-14 11:19:18 +03:00
parent d6b9ee59a5
commit 1139ca97f7
7 changed files with 281 additions and 218 deletions

View File

@@ -13,6 +13,7 @@
#include <cstddef>
#include <algorithm>
#include <iterator>
#include <utility>
#include <boost/assert.hpp>
#include <boost/range.hpp>
@@ -30,6 +31,7 @@
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
@@ -45,44 +47,36 @@ namespace detail { namespace distance
template
<
typename PointOrSegmentIterator,
typename Geometry,
typename Strategy
>
class point_or_segment_range_to_geometry_rtree
{
private:
typedef typename strategy::distance::services::comparable_type
typedef typename std::iterator_traits
<
Strategy
>::type comparable_strategy;
PointOrSegmentIterator
>::value_type point_or_segment_type;
typedef iterator_selector<Geometry const> selector_type;
typedef detail::closest_feature::range_to_range_rtree range_to_range;
public:
template <typename PointOrSegmentIterator>
static inline
typename strategy::distance::services::return_type
typedef typename strategy::distance::services::return_type
<
Strategy,
typename point_type
<
typename std::iterator_traits
<
PointOrSegmentIterator
>::value_type
>::type,
typename point_type<point_or_segment_type>::type,
typename point_type<Geometry>::type
>::type
apply(PointOrSegmentIterator first,
PointOrSegmentIterator beyond,
Geometry const& geometry,
Strategy const& strategy)
{
typedef iterator_selector<Geometry const> selector_type;
>::type return_type;
typedef detail::closest_feature::range_to_range_rtree
<
PointOrSegmentIterator,
typename selector_type::iterator_type
> closest_features_type;
static inline return_type apply(PointOrSegmentIterator first,
PointOrSegmentIterator beyond,
Geometry const& geometry,
Strategy const& strategy)
{
namespace sds = strategy::distance::services;
BOOST_ASSERT( first != beyond );
@@ -90,38 +84,47 @@ public:
{
return dispatch::distance
<
typename std::iterator_traits
<
PointOrSegmentIterator
>::value_type,
Geometry,
Strategy
point_or_segment_type, Geometry, Strategy
>::apply(*first, geometry, strategy);
}
comparable_strategy cstrategy
= strategy::distance::services::get_comparable
<
Strategy
>::apply(strategy);
typename closest_features_type::return_type cf
= closest_features_type::apply(first,
beyond,
selector_type::begin(geometry),
selector_type::end(geometry),
cstrategy);
return dispatch::distance
point_or_segment_type rtree_value_min;
typename selector_type::iterator_type qit_min;
typename sds::return_type
<
typename closest_features_type::return_type::first_type,
typename std::iterator_traits
<
typename closest_features_type::return_type::second_type
>::value_type,
Strategy
>::apply(cf.first, *cf.second, strategy);
typename sds::comparable_type<Strategy>::type,
typename point_type<point_or_segment_type>::type,
typename point_type<Geometry>::type
>::type cd_min;
std::pair
<
point_or_segment_type,
typename selector_type::iterator_type
> cf = range_to_range::apply(first,
beyond,
selector_type::begin(geometry),
selector_type::end(geometry),
sds::get_comparable
<
Strategy
>::apply(strategy),
cd_min);
return
is_comparable<Strategy>::value
?
cd_min
:
dispatch::distance
<
point_or_segment_type,
typename std::iterator_traits
<
typename selector_type::iterator_type
>::value_type,
Strategy
>::apply(cf.first, *cf.second, strategy);
}
};
@@ -148,6 +151,15 @@ private:
Strategy
>::type comparable_strategy;
typedef typename strategy::distance::services::return_type
<
comparable_strategy,
typename point_type<Geometry1>::type,
typename point_type<Geometry2>::type
>::type comparable_return_type;
typedef detail::closest_feature::range_to_range_rtree range_to_range;
public:
typedef typename strategy::distance::services::return_type
<
@@ -164,22 +176,6 @@ public:
typedef geometry::point_iterator<Geometry1 const> const_point_iterator1;
typedef geometry::point_iterator<Geometry2 const> const_point_iterator2;
typedef detail::closest_feature::range_to_range_rtree
<
const_point_iterator1,
geometry::segment_iterator<Geometry2 const>
> closest_features_type12;
typedef typename closest_features_type12::return_type return_type12;
typedef detail::closest_feature::range_to_range_rtree
<
const_point_iterator2,
geometry::segment_iterator<Geometry1 const>
> closest_features_type21;
typedef typename closest_features_type21::return_type return_type21;
const_point_iterator1 first1 = points_begin(geometry1);
const_point_iterator1 beyond1 = points_end(geometry1);
const_point_iterator2 first2 = points_begin(geometry2);
@@ -216,41 +212,57 @@ public:
Strategy
>::apply(strategy);
return_type12 cf12
= closest_features_type12::apply(first1,
beyond1,
segments_begin(geometry2),
segments_end(geometry2),
cstrategy);
return_type21 cf21
= closest_features_type21::apply(first2,
beyond2,
segments_begin(geometry1),
segments_end(geometry1),
cstrategy);
return_type dist1 = dispatch::distance
comparable_return_type cdist12;
std::pair
<
typename point_type<Geometry1>::type,
typename std::iterator_traits
<
typename return_type12::second_type
>::value_type,
Strategy
>::apply(cf12.first, *cf12.second, strategy);
geometry::segment_iterator<Geometry2 const>
> cf12 = range_to_range::apply(first1,
beyond1,
segments_begin(geometry2),
segments_end(geometry2),
cstrategy,
cdist12);
return_type dist2 = dispatch::distance
comparable_return_type cdist21;
std::pair
<
typename point_type<Geometry2>::type,
geometry::segment_iterator<Geometry1 const>
> cf21 = range_to_range::apply(first2,
beyond2,
segments_begin(geometry1),
segments_end(geometry1),
cstrategy,
cdist21);
if ( is_comparable<Strategy>::value )
{
return (std::min)(cdist12, cdist21);
}
if ( cdist12 < cdist21 )
{
return dispatch::distance
<
typename point_type<Geometry1>::type,
typename std::iterator_traits
<
geometry::segment_iterator<Geometry2 const>
>::value_type,
Strategy
>::apply(cf12.first, *cf12.second, strategy);
}
return dispatch::distance
<
typename point_type<Geometry2>::type,
typename std::iterator_traits
<
typename return_type21::second_type
geometry::segment_iterator<Geometry1 const>
>::value_type,
Strategy
>::apply(cf21.first, *cf21.second, strategy);
return (std::min)(dist1, dist2);
}
};

View File

@@ -33,6 +33,8 @@
#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
namespace boost { namespace geometry
{
@@ -74,17 +76,6 @@ template
typename Tag = typename tag<Geometry>::type
>
class geometry_to_segment_or_box
: detail::closest_feature::point_to_point_range
<
typename point_type<Geometry>::type,
std::vector<typename point_type<SegmentOrBox>::type>,
segment_or_box_point_range_closure<SegmentOrBox>::value,
typename strategy::distance::services::comparable_type
<
Strategy
>::type
>,
detail::closest_feature::geometry_to_range
{
private:
typedef typename point_type<SegmentOrBox>::type segment_or_box_point;
@@ -100,9 +91,9 @@ private:
std::vector<segment_or_box_point>,
segment_or_box_point_range_closure<SegmentOrBox>::value,
comparable_strategy
> base_type1;
> point_to_point_range;
typedef detail::closest_feature::geometry_to_range base_type2;
typedef detail::closest_feature::geometry_to_range geometry_to_range;
typedef typename strategy::distance::services::return_type
<
@@ -233,22 +224,23 @@ public:
for (point_iterator_type pit = points_begin(geometry);
pit != points_end(geometry); ++pit, first = false)
{
seg_or_box_iterator_type it1, it2;
comparable_return_type cd;
base_type1::apply(*pit,
seg_or_box_points.begin(),
seg_or_box_points.end(),
cstrategy,
it1,
it2,
cd);
std::pair
<
seg_or_box_iterator_type, seg_or_box_iterator_type
> it_pair
= point_to_point_range::apply(*pit,
seg_or_box_points.begin(),
seg_or_box_points.end(),
cstrategy,
cd);
if ( first || cd < cd_min1 )
{
cd_min1 = cd;
pit_min = pit;
assign_new_value::apply(it_min1, it1);
assign_new_value::apply(it_min2, it2);
assign_new_value::apply(it_min1, it_pair.first);
assign_new_value::apply(it_min2, it_pair.second);
}
}
@@ -263,14 +255,13 @@ public:
= seg_or_box_points.begin();
it != seg_or_box_points.end(); ++it, first = false)
{
segment_iterator_type sit;
comparable_return_type cd;
base_type2::apply(*it,
segments_begin(geometry),
segments_end(geometry),
cstrategy,
sit,
cd);
segment_iterator_type sit
= geometry_to_range::apply(*it,
segments_begin(geometry),
segments_end(geometry),
cstrategy,
cd);
if ( first || cd < cd_min2 )
{
@@ -280,6 +271,11 @@ public:
}
}
if ( is_comparable<Strategy>::value )
{
return (std::min)(cd_min1, cd_min2);
}
if ( cd_min1 < cd_min2 )
{
return strategy.apply(*pit_min, *it_min1, *it_min2);
@@ -313,21 +309,18 @@ template <typename MultiPoint, typename SegmentOrBox, typename Strategy>
class geometry_to_segment_or_box
<
MultiPoint, SegmentOrBox, Strategy, multi_point_tag
> : detail::closest_feature::geometry_to_range
>
{
private:
typedef detail::closest_feature::geometry_to_range base_type;
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type comparable_strategy;
typedef typename boost::range_iterator
<
MultiPoint const
>::type iterator_type;
typedef detail::closest_feature::geometry_to_range geometry_to_range;
public:
typedef typename strategy::distance::services::return_type
<
@@ -342,18 +335,34 @@ public:
{
namespace sds = strategy::distance::services;
iterator_type it_min
= base_type::apply(segment_or_box,
boost::begin(multipoint),
boost::end(multipoint),
sds::get_comparable<Strategy>::apply(strategy));
return dispatch::distance
typename sds::return_type
<
typename point_type<MultiPoint>::type,
SegmentOrBox,
Strategy
>::apply(*it_min, segment_or_box, strategy);
typename sds::comparable_type<Strategy>::type,
typename point_type<SegmentOrBox>::type,
typename point_type<MultiPoint>::type
>::type cd_min;
iterator_type it_min
= geometry_to_range::apply(segment_or_box,
boost::begin(multipoint),
boost::end(multipoint),
sds::get_comparable
<
Strategy
>::apply(strategy),
cd_min);
return
is_comparable<Strategy>::value
?
cd_min
:
dispatch::distance
<
typename point_type<MultiPoint>::type,
SegmentOrBox,
Strategy
>::apply(*it_min, segment_or_box, strategy);
}
};

View File

@@ -83,7 +83,9 @@ struct linear_to_linear<Linear1, Linear2, Strategy, true>
{
return point_or_segment_range_to_geometry_rtree
<
Linear1, Strategy
geometry::segment_iterator<Linear2 const>,
Linear1,
Strategy
>::apply(geometry::segments_begin(linear2),
geometry::segments_end(linear2),
linear1,
@@ -93,7 +95,9 @@ struct linear_to_linear<Linear1, Linear2, Strategy, true>
return point_or_segment_range_to_geometry_rtree
<
Linear2, Strategy
geometry::segment_iterator<Linear1 const>,
Linear2,
Strategy
>::apply(geometry::segments_begin(linear1),
geometry::segments_end(linear1),
linear2,

View File

@@ -53,7 +53,9 @@ struct multipoint_to_multipoint
{
return point_or_segment_range_to_geometry_rtree
<
MultiPoint1, Strategy
typename boost::range_iterator<MultiPoint2 const>::type,
MultiPoint1,
Strategy
>::apply(boost::begin(multipoint2),
boost::end(multipoint2),
multipoint1,
@@ -62,7 +64,9 @@ struct multipoint_to_multipoint
return point_or_segment_range_to_geometry_rtree
<
MultiPoint2, Strategy
typename boost::range_iterator<MultiPoint1 const>::type,
MultiPoint2,
Strategy
>::apply(boost::begin(multipoint1),
boost::end(multipoint1),
multipoint2,
@@ -87,7 +91,9 @@ struct multipoint_to_linear
{
return detail::distance::point_or_segment_range_to_geometry_rtree
<
Linear, Strategy
typename boost::range_iterator<MultiPoint const>::type,
Linear,
Strategy
>::apply(boost::begin(multipoint),
boost::end(multipoint),
linear,
@@ -149,7 +155,9 @@ public:
return detail::distance::point_or_segment_range_to_geometry_rtree
<
Areal, Strategy
typename boost::range_iterator<MultiPoint const>::type,
Areal,
Strategy
>::apply(boost::begin(multipoint),
boost::end(multipoint),
areal,

View File

@@ -42,6 +42,7 @@
#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
@@ -86,7 +87,7 @@ private:
typedef detail::closest_feature::point_to_point_range
<
Point, Range, Closure, comparable_strategy
> closest_feature_type;
> point_to_point_range;
public:
typedef typename strategy::distance::services::return_type
@@ -108,15 +109,33 @@ public:
namespace sds = strategy::distance::services;
typename closest_feature_type::return_type cf
= closest_feature_type::apply(point,
range,
typename sds::return_type
<
comparable_strategy,
Point,
typename point_type<Range>::type
>::type cd_min;
std::pair
<
typename boost::range_iterator<Range const>::type,
typename boost::range_iterator<Range const>::type
> it_pair
= point_to_point_range::apply(point,
boost::begin(range),
boost::end(range),
sds::get_comparable
<
Strategy
>::apply(strategy));
>::apply(strategy),
cd_min);
return strategy.apply(point, *cf.first, *cf.second);
return
is_comparable<Strategy>::value
?
cd_min
:
strategy.apply(point, *it_pair.first, *it_pair.second);
}
};
@@ -144,7 +163,7 @@ struct point_to_ring
return return_type(0);
}
return detail::distance::point_to_range
return point_to_range
<
Point, Ring, closure<Ring>::value, Strategy
>::apply(point, ring, strategy);
@@ -237,10 +256,7 @@ template
class point_to_multigeometry
{
private:
typedef typename strategy::distance::services::comparable_type
<
Strategy
>::type comparable_strategy;
typedef detail::closest_feature::geometry_to_range geometry_to_range;
public:
typedef typename strategy::distance::services::return_type
@@ -256,27 +272,39 @@ public:
{
typedef iterator_selector<MultiGeometry const> selector_type;
typedef detail::closest_feature::geometry_to_range point_to_range;
namespace sds = strategy::distance::services;
typename selector_type::iterator_type it_min
= point_to_range::apply(point,
selector_type::begin(multigeometry),
selector_type::end(multigeometry),
sds::get_comparable
<
Strategy
>::apply(strategy));
return dispatch::distance
typename sds::return_type
<
typename sds::comparable_type<Strategy>::type,
Point,
typename std::iterator_traits
<
typename selector_type::iterator_type
>::value_type,
Strategy
>::apply(point, *it_min, strategy);
typename point_type<MultiGeometry>::type
>::type cd;
typename selector_type::iterator_type it_min
= geometry_to_range::apply(point,
selector_type::begin(multigeometry),
selector_type::end(multigeometry),
sds::get_comparable
<
Strategy
>::apply(strategy),
cd);
return
is_comparable<Strategy>::value
?
cd
:
dispatch::distance
<
Point,
typename std::iterator_traits
<
typename selector_type::iterator_type
>::value_type,
Strategy
>::apply(point, *it_min, strategy);
}
};

View File

@@ -42,7 +42,7 @@
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
#include <boost/geometry/algorithms/detail/distance/point_to_geometry.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
@@ -65,16 +65,6 @@ template
bool UsePointBoxStrategy = false
>
class segment_to_box_2D_generic
: detail::closest_feature::point_to_point_range
<
typename point_type<Segment>::type,
std::vector<typename point_type<Box>::type>,
open,
typename strategy::distance::services::comparable_type
<
Strategy
>::type
>
{
private:
typedef typename point_type<Segment>::type segment_point;
@@ -91,18 +81,13 @@ private:
std::vector<box_point>,
open,
comparable_strategy
> base_type;
> point_to_point_range;
typedef typename strategy::distance::services::return_type
<
comparable_strategy, segment_point, box_point
>::type comparable_return_type;
typedef point_to_range
<
segment_point, std::vector<box_point>, open, comparable_strategy
> point_to_box_boundary;
public:
typedef typename strategy::distance::services::return_type
<
@@ -140,19 +125,22 @@ public:
cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);
}
typename std::vector<box_point>::const_iterator bit_min1[2];
typename std::vector<box_point>::const_iterator bit_min2[2];
std::pair
<
typename std::vector<box_point>::const_iterator,
typename std::vector<box_point>::const_iterator
> bit_min[2];
base_type::apply(p[0],
box_points.begin(), box_points.end(),
cstrategy,
bit_min1[0], bit_min2[0],
cd[4]);
base_type::apply(p[1],
box_points.begin(), box_points.end(),
cstrategy,
bit_min1[1], bit_min2[1],
cd[5]);
bit_min[0] = point_to_point_range::apply(p[0],
box_points.begin(),
box_points.end(),
cstrategy,
cd[4]);
bit_min[1] = point_to_point_range::apply(p[1],
box_points.begin(),
box_points.end(),
cstrategy,
cd[5]);
unsigned int imin = 0;
for (unsigned int i = 1; i < 6; ++i)
@@ -163,6 +151,11 @@ public:
}
}
if ( is_comparable<Strategy>::value )
{
return cd[imin];
}
if ( imin < 4 )
{
return strategy.apply(box_points[imin], p[0], p[1]);
@@ -170,7 +163,9 @@ public:
else
{
unsigned int bimin = imin - 4;
return strategy.apply(p[bimin], *bit_min1[bimin], *bit_min2[bimin]);
return strategy.apply(p[bimin],
*bit_min[bimin].first,
*bit_min[bimin].second);
}
}
};
@@ -198,12 +193,14 @@ private:
comparable_strategy, segment_point, box_point
>::type comparable_return_type;
typedef typename detail::distance::default_strategy
<
segment_point, Box
>::type point_box_strategy;
typedef typename strategy::distance::services::comparable_type
<
typename detail::distance::default_strategy
<
segment_point, Box
>::type
point_box_strategy
>::type point_box_comparable_strategy;
public:
@@ -258,20 +255,18 @@ public:
}
}
if ( is_comparable<Strategy>::value )
{
return cd[imin];
}
if ( imin < 4 )
{
return strategy.apply(box_points[imin], p[0], p[1]);
strategy.apply(box_points[imin], p[0], p[1]);
}
else
{
typename detail::distance::default_strategy
<
segment_point, Box
>::type pb_strategy;
boost::ignore_unused(pb_strategy);
return pb_strategy.apply(p[imin - 4], box);
return point_box_strategy().apply(p[imin - 4], box);
}
}
};

View File

@@ -24,6 +24,8 @@
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
@@ -94,6 +96,11 @@ public:
std::size_t imin = std::distance(boost::addressof(d[0]),
std::min_element(d, d + 4));
if ( is_comparable<Strategy>::value )
{
return d[imin];
}
switch (imin)
{
case 0: