File indexing completed on 2025-01-18 09:35:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_GEOMETRY_ALGORITHMS_DISCRETE_HAUSDORFF_DISTANCE_HPP
0016 #define BOOST_GEOMETRY_ALGORITHMS_DISCRETE_HAUSDORFF_DISTANCE_HPP
0017
0018 #include <algorithm>
0019
0020 #ifdef BOOST_GEOMETRY_DEBUG_HAUSDORFF_DISTANCE
0021 #include <iostream>
0022 #endif
0023
0024 #include <iterator>
0025 #include <utility>
0026 #include <vector>
0027 #include <limits>
0028
0029 #include <boost/range/size.hpp>
0030
0031 #include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
0032 #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
0033 #include <boost/geometry/algorithms/not_implemented.hpp>
0034 #include <boost/geometry/core/point_type.hpp>
0035 #include <boost/geometry/core/tag.hpp>
0036 #include <boost/geometry/core/tags.hpp>
0037 #include <boost/geometry/strategies/detail.hpp>
0038 #include <boost/geometry/strategies/discrete_distance/cartesian.hpp>
0039 #include <boost/geometry/strategies/discrete_distance/geographic.hpp>
0040 #include <boost/geometry/strategies/discrete_distance/spherical.hpp>
0041 #include <boost/geometry/strategies/distance_result.hpp>
0042 #include <boost/geometry/util/range.hpp>
0043
0044
0045
0046 #ifdef BOOST_GEOMETRY_ENABLE_SIMILARITY_RTREE
0047 #include <boost/geometry/index/rtree.hpp>
0048 #endif
0049
0050 namespace boost { namespace geometry
0051 {
0052
0053 #ifndef DOXYGEN_NO_DETAIL
0054 namespace detail { namespace discrete_hausdorff_distance
0055 {
0056
0057
0058
0059 struct point_range
0060 {
0061 template <typename Point, typename Range, typename Strategies>
0062 static inline auto apply(Point const& pnt, Range const& rng,
0063 Strategies const& strategies)
0064 {
0065 typedef typename distance_result
0066 <
0067 Point,
0068 typename point_type<Range>::type,
0069 Strategies
0070 >::type result_type;
0071
0072 typedef typename boost::range_size<Range>::type size_type;
0073
0074 boost::geometry::detail::throw_on_empty_input(rng);
0075
0076 auto const strategy = strategies.distance(dummy_point(), dummy_point());
0077
0078 size_type const n = boost::size(rng);
0079 result_type dis_min = 0;
0080 bool is_dis_min_set = false;
0081
0082 for (size_type i = 0 ; i < n ; i++)
0083 {
0084 result_type dis_temp = strategy.apply(pnt, range::at(rng, i));
0085 if (! is_dis_min_set || dis_temp < dis_min)
0086 {
0087 dis_min = dis_temp;
0088 is_dis_min_set = true;
0089 }
0090 }
0091 return dis_min;
0092 }
0093 };
0094
0095 struct range_range
0096 {
0097 template <typename Range1, typename Range2, typename Strategies>
0098 static inline auto apply(Range1 const& r1, Range2 const& r2,
0099 Strategies const& strategies)
0100 {
0101 typedef typename distance_result
0102 <
0103 typename point_type<Range1>::type,
0104 typename point_type<Range2>::type,
0105 Strategies
0106 >::type result_type;
0107
0108 typedef typename boost::range_size<Range1>::type size_type;
0109
0110 boost::geometry::detail::throw_on_empty_input(r1);
0111 boost::geometry::detail::throw_on_empty_input(r2);
0112
0113 size_type const n = boost::size(r1);
0114 result_type dis_max = 0;
0115
0116 #ifdef BOOST_GEOMETRY_ENABLE_SIMILARITY_RTREE
0117 namespace bgi = boost::geometry::index;
0118 typedef typename point_type<Range1>::type point_t;
0119 typedef bgi::rtree<point_t, bgi::linear<4> > rtree_type;
0120 rtree_type rtree(boost::begin(r2), boost::end(r2));
0121 point_t res;
0122 #endif
0123
0124 for (size_type i = 0 ; i < n ; i++)
0125 {
0126 #ifdef BOOST_GEOMETRY_ENABLE_SIMILARITY_RTREE
0127 size_type found = rtree.query(bgi::nearest(range::at(r1, i), 1), &res);
0128 result_type dis_min = strategy.apply(range::at(r1,i), res);
0129 #else
0130 result_type dis_min = point_range::apply(range::at(r1, i), r2, strategies);
0131 #endif
0132 if (dis_min > dis_max )
0133 {
0134 dis_max = dis_min;
0135 }
0136 }
0137 return dis_max;
0138 }
0139 };
0140
0141
0142 struct range_multi_range
0143 {
0144 template <typename Range, typename Multi_range, typename Strategies>
0145 static inline auto apply(Range const& rng, Multi_range const& mrng,
0146 Strategies const& strategies)
0147 {
0148 typedef typename distance_result
0149 <
0150 typename point_type<Range>::type,
0151 typename point_type<Multi_range>::type,
0152 Strategies
0153 >::type result_type;
0154 typedef typename boost::range_size<Multi_range>::type size_type;
0155
0156 boost::geometry::detail::throw_on_empty_input(rng);
0157 boost::geometry::detail::throw_on_empty_input(mrng);
0158
0159 size_type b = boost::size(mrng);
0160 result_type haus_dis = 0;
0161
0162 for (size_type j = 0 ; j < b ; j++)
0163 {
0164 result_type dis_max = range_range::apply(rng, range::at(mrng, j), strategies);
0165 if (dis_max > haus_dis)
0166 {
0167 haus_dis = dis_max;
0168 }
0169 }
0170
0171 return haus_dis;
0172 }
0173 };
0174
0175
0176 struct multi_range_multi_range
0177 {
0178 template <typename Multi_Range1, typename Multi_range2, typename Strategies>
0179 static inline auto apply(Multi_Range1 const& mrng1, Multi_range2 const& mrng2,
0180 Strategies const& strategies)
0181 {
0182 typedef typename distance_result
0183 <
0184 typename point_type<Multi_Range1>::type,
0185 typename point_type<Multi_range2>::type,
0186 Strategies
0187 >::type result_type;
0188 typedef typename boost::range_size<Multi_Range1>::type size_type;
0189
0190 boost::geometry::detail::throw_on_empty_input(mrng1);
0191 boost::geometry::detail::throw_on_empty_input(mrng2);
0192
0193 size_type n = boost::size(mrng1);
0194 result_type haus_dis = 0;
0195
0196 for (size_type i = 0 ; i < n ; i++)
0197 {
0198 result_type dis_max = range_multi_range::apply(range::at(mrng1, i), mrng2, strategies);
0199 if (dis_max > haus_dis)
0200 {
0201 haus_dis = dis_max;
0202 }
0203 }
0204 return haus_dis;
0205 }
0206 };
0207
0208 }}
0209 #endif
0210
0211 #ifndef DOXYGEN_NO_DISPATCH
0212 namespace dispatch
0213 {
0214 template
0215 <
0216 typename Geometry1,
0217 typename Geometry2,
0218 typename Tag1 = typename tag<Geometry1>::type,
0219 typename Tag2 = typename tag<Geometry2>::type
0220 >
0221 struct discrete_hausdorff_distance : not_implemented<Tag1, Tag2>
0222 {};
0223
0224
0225 template <typename Point, typename MultiPoint>
0226 struct discrete_hausdorff_distance<Point, MultiPoint, point_tag, multi_point_tag>
0227 : detail::discrete_hausdorff_distance::point_range
0228 {};
0229
0230
0231 template <typename Linestring1, typename Linestring2>
0232 struct discrete_hausdorff_distance<Linestring1, Linestring2, linestring_tag, linestring_tag>
0233 : detail::discrete_hausdorff_distance::range_range
0234 {};
0235
0236
0237 template <typename MultiPoint1, typename MultiPoint2>
0238 struct discrete_hausdorff_distance<MultiPoint1, MultiPoint2, multi_point_tag, multi_point_tag>
0239 : detail::discrete_hausdorff_distance::range_range
0240 {};
0241
0242
0243 template <typename Linestring, typename MultiLinestring>
0244 struct discrete_hausdorff_distance<Linestring, MultiLinestring, linestring_tag, multi_linestring_tag>
0245 : detail::discrete_hausdorff_distance::range_multi_range
0246 {};
0247
0248
0249 template <typename MultiLinestring1, typename MultiLinestring2>
0250 struct discrete_hausdorff_distance<MultiLinestring1, MultiLinestring2, multi_linestring_tag, multi_linestring_tag>
0251 : detail::discrete_hausdorff_distance::multi_range_multi_range
0252 {};
0253
0254 }
0255 #endif
0256
0257
0258 namespace resolve_strategy {
0259
0260 template
0261 <
0262 typename Strategies,
0263 bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
0264 >
0265 struct discrete_hausdorff_distance
0266 {
0267 template <typename Geometry1, typename Geometry2>
0268 static inline auto apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
0269 Strategies const& strategies)
0270 {
0271 return dispatch::discrete_hausdorff_distance
0272 <
0273 Geometry1, Geometry2
0274 >::apply(geometry1, geometry2, strategies);
0275 }
0276 };
0277
0278 template <typename Strategy>
0279 struct discrete_hausdorff_distance<Strategy, false>
0280 {
0281 template <typename Geometry1, typename Geometry2>
0282 static inline auto apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
0283 Strategy const& strategy)
0284 {
0285 using strategies::discrete_distance::services::strategy_converter;
0286 return dispatch::discrete_hausdorff_distance
0287 <
0288 Geometry1, Geometry2
0289 >::apply(geometry1, geometry2,
0290 strategy_converter<Strategy>::get(strategy));
0291 }
0292 };
0293
0294 template <>
0295 struct discrete_hausdorff_distance<default_strategy, false>
0296 {
0297 template <typename Geometry1, typename Geometry2>
0298 static inline auto apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
0299 default_strategy const&)
0300 {
0301 typedef typename strategies::discrete_distance::services::default_strategy
0302 <
0303 Geometry1, Geometry2
0304 >::type strategies_type;
0305
0306 return dispatch::discrete_hausdorff_distance
0307 <
0308 Geometry1, Geometry2
0309 >::apply(geometry1, geometry2, strategies_type());
0310 }
0311 };
0312
0313 }
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342 template <typename Geometry1, typename Geometry2, typename Strategy>
0343 inline auto discrete_hausdorff_distance(Geometry1 const& geometry1,
0344 Geometry2 const& geometry2,
0345 Strategy const& strategy)
0346 {
0347 return resolve_strategy::discrete_hausdorff_distance
0348 <
0349 Strategy
0350 >::apply(geometry1, geometry2, strategy);
0351 }
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371 template <typename Geometry1, typename Geometry2>
0372 inline auto discrete_hausdorff_distance(Geometry1 const& geometry1,
0373 Geometry2 const& geometry2)
0374 {
0375 return resolve_strategy::discrete_hausdorff_distance
0376 <
0377 default_strategy
0378 >::apply(geometry1, geometry2, default_strategy());
0379 }
0380
0381 }}
0382
0383 #endif