diff --git a/include/boost/geometry/algorithms/detail/distance/geometry_to_geometry_rtree.hpp b/include/boost/geometry/algorithms/detail/distance/geometry_to_geometry_rtree.hpp index 2f9aa3812..ac9a0bdcb 100644 --- a/include/boost/geometry/algorithms/detail/distance/geometry_to_geometry_rtree.hpp +++ b/include/boost/geometry/algorithms/detail/distance/geometry_to_geometry_rtree.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,7 @@ #include #include +#include #include @@ -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 selector_type; + + typedef detail::closest_feature::range_to_range_rtree range_to_range; public: - template - 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::type, typename point_type::type - >::type - apply(PointOrSegmentIterator first, - PointOrSegmentIterator beyond, - Geometry const& geometry, - Strategy const& strategy) - { - typedef iterator_selector 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::type, + typename point_type::type, + typename point_type::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::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::type, + typename point_type::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 const_point_iterator1; typedef geometry::point_iterator const_point_iterator2; - typedef detail::closest_feature::range_to_range_rtree - < - const_point_iterator1, - geometry::segment_iterator - > 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 - > 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::type, - typename std::iterator_traits - < - typename return_type12::second_type - >::value_type, - Strategy - >::apply(cf12.first, *cf12.second, strategy); + geometry::segment_iterator + > 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::type, + geometry::segment_iterator + > cf21 = range_to_range::apply(first2, + beyond2, + segments_begin(geometry1), + segments_end(geometry1), + cstrategy, + cdist21); + + if ( is_comparable::value ) + { + return (std::min)(cdist12, cdist21); + } + + if ( cdist12 < cdist21 ) + { + return dispatch::distance + < + typename point_type::type, + typename std::iterator_traits + < + geometry::segment_iterator + >::value_type, + Strategy + >::apply(cf12.first, *cf12.second, strategy); + } + + return dispatch::distance < typename point_type::type, typename std::iterator_traits < - typename return_type21::second_type + geometry::segment_iterator >::value_type, Strategy >::apply(cf21.first, *cf21.second, strategy); - - return (std::min)(dist1, dist2); } }; diff --git a/include/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp b/include/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp index 1e5520d2d..fc4924a13 100644 --- a/include/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp +++ b/include/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp @@ -33,6 +33,8 @@ #include #include +#include + namespace boost { namespace geometry { @@ -74,17 +76,6 @@ template typename Tag = typename tag::type > class geometry_to_segment_or_box - : detail::closest_feature::point_to_point_range - < - typename point_type::type, - std::vector::type>, - segment_or_box_point_range_closure::value, - typename strategy::distance::services::comparable_type - < - Strategy - >::type - >, - detail::closest_feature::geometry_to_range { private: typedef typename point_type::type segment_or_box_point; @@ -100,9 +91,9 @@ private: std::vector, segment_or_box_point_range_closure::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::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 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::apply(strategy)); - - return dispatch::distance + typename sds::return_type < - typename point_type::type, - SegmentOrBox, - Strategy - >::apply(*it_min, segment_or_box, strategy); + typename sds::comparable_type::type, + typename point_type::type, + typename point_type::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::value + ? + cd_min + : + dispatch::distance + < + typename point_type::type, + SegmentOrBox, + Strategy + >::apply(*it_min, segment_or_box, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp b/include/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp index a8bc955de..ecacd6fb4 100644 --- a/include/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp +++ b/include/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp @@ -83,7 +83,9 @@ struct linear_to_linear { return point_or_segment_range_to_geometry_rtree < - Linear1, Strategy + geometry::segment_iterator, + Linear1, + Strategy >::apply(geometry::segments_begin(linear2), geometry::segments_end(linear2), linear1, @@ -93,7 +95,9 @@ struct linear_to_linear return point_or_segment_range_to_geometry_rtree < - Linear2, Strategy + geometry::segment_iterator, + Linear2, + Strategy >::apply(geometry::segments_begin(linear1), geometry::segments_end(linear1), linear2, diff --git a/include/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp b/include/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp index e18ddb4dd..273c18a52 100644 --- a/include/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp @@ -53,7 +53,9 @@ struct multipoint_to_multipoint { return point_or_segment_range_to_geometry_rtree < - MultiPoint1, Strategy + typename boost::range_iterator::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::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::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::type, + Areal, + Strategy >::apply(boost::begin(multipoint), boost::end(multipoint), areal, diff --git a/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp b/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp index ae6f21474..264d0ab9d 100644 --- a/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/distance/point_to_geometry.hpp @@ -42,6 +42,7 @@ #include #include +#include #include #include @@ -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::type + >::type cd_min; + + std::pair + < + typename boost::range_iterator::type, + typename boost::range_iterator::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::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::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 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::type, Point, - typename std::iterator_traits - < - typename selector_type::iterator_type - >::value_type, - Strategy - >::apply(point, *it_min, strategy); + typename point_type::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::value + ? + cd + : + dispatch::distance + < + Point, + typename std::iterator_traits + < + typename selector_type::iterator_type + >::value_type, + Strategy + >::apply(point, *it_min, strategy); } }; diff --git a/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp b/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp index 7f88a93b9..e73db2571 100644 --- a/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp +++ b/include/boost/geometry/algorithms/detail/distance/segment_to_box.hpp @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include @@ -65,16 +65,6 @@ template bool UsePointBoxStrategy = false > class segment_to_box_2D_generic - : detail::closest_feature::point_to_point_range - < - typename point_type::type, - std::vector::type>, - open, - typename strategy::distance::services::comparable_type - < - Strategy - >::type - > { private: typedef typename point_type::type segment_point; @@ -91,18 +81,13 @@ private: std::vector, 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, 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::const_iterator bit_min1[2]; - typename std::vector::const_iterator bit_min2[2]; + std::pair + < + typename std::vector::const_iterator, + typename std::vector::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::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::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); } } }; diff --git a/include/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp b/include/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp index 5ecc15800..adccfd0bc 100644 --- a/include/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp +++ b/include/boost/geometry/algorithms/detail/distance/segment_to_segment.hpp @@ -24,6 +24,8 @@ #include #include +#include + #include @@ -94,6 +96,11 @@ public: std::size_t imin = std::distance(boost::addressof(d[0]), std::min_element(d, d + 4)); + if ( is_comparable::value ) + { + return d[imin]; + } + switch (imin) { case 0: