File indexing completed on 2025-01-18 09:35:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #ifndef BOOST_GEOMETRY_ALGORITHMS_LENGTH_HPP
0021 #define BOOST_GEOMETRY_ALGORITHMS_LENGTH_HPP
0022
0023 #include <boost/range/begin.hpp>
0024 #include <boost/range/end.hpp>
0025 #include <boost/range/value_type.hpp>
0026
0027 #include "boost/geometry/algorithms/detail/assign_indexed_point.hpp"
0028 #include <boost/geometry/algorithms/detail/calculate_null.hpp>
0029 #include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
0030 #include <boost/geometry/algorithms/detail/multi_sum.hpp>
0031
0032 #include <boost/geometry/algorithms/detail/visit.hpp>
0033
0034 #include <boost/geometry/core/closure.hpp>
0035 #include <boost/geometry/core/tag.hpp>
0036 #include <boost/geometry/core/tags.hpp>
0037 #include <boost/geometry/core/visit.hpp>
0038
0039 #include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
0040 #include <boost/geometry/geometries/concepts/check.hpp>
0041
0042 #include <boost/geometry/strategies/default_strategy.hpp>
0043 #include <boost/geometry/strategies/default_length_result.hpp> // TODO: Move to algorithms
0044 #include <boost/geometry/strategies/detail.hpp>
0045 #include <boost/geometry/strategies/length/cartesian.hpp>
0046 #include <boost/geometry/strategies/length/geographic.hpp>
0047 #include <boost/geometry/strategies/length/spherical.hpp>
0048
0049 #include <boost/geometry/views/closeable_view.hpp>
0050
0051 namespace boost { namespace geometry
0052 {
0053
0054
0055 #ifndef DOXYGEN_NO_DETAIL
0056 namespace detail { namespace length
0057 {
0058
0059
0060 template<typename Segment>
0061 struct segment_length
0062 {
0063 template <typename Strategies>
0064 static inline typename default_length_result<Segment>::type
0065 apply(Segment const& segment, Strategies const& strategies)
0066 {
0067 typedef typename point_type<Segment>::type point_type;
0068 point_type p1, p2;
0069 geometry::detail::assign_point_from_index<0>(segment, p1);
0070 geometry::detail::assign_point_from_index<1>(segment, p2);
0071 return strategies.distance(p1, p2).apply(p1, p2);
0072 }
0073 };
0074
0075
0076
0077
0078
0079
0080
0081 template<typename Range, closure_selector Closure>
0082 struct range_length
0083 {
0084 typedef typename default_length_result<Range>::type return_type;
0085
0086 template <typename Strategies>
0087 static inline return_type
0088 apply(Range const& range, Strategies const& strategies)
0089 {
0090 return_type sum = return_type();
0091 detail::closed_view<Range const> const view(range);
0092 auto it = boost::begin(view);
0093 auto const end = boost::end(view);
0094 if (it != end)
0095 {
0096 auto const strategy = strategies.distance(dummy_point(), dummy_point());
0097
0098 for(auto previous = it++; it != end; ++previous, ++it)
0099 {
0100
0101
0102 sum += strategy.apply(*previous, *it);
0103 }
0104 }
0105
0106 return sum;
0107 }
0108 };
0109
0110
0111 }}
0112 #endif
0113
0114
0115 #ifndef DOXYGEN_NO_DISPATCH
0116 namespace dispatch
0117 {
0118
0119
0120 template <typename Geometry, typename Tag = typename tag<Geometry>::type>
0121 struct length : detail::calculate_null
0122 {
0123 typedef typename default_length_result<Geometry>::type return_type;
0124
0125 template <typename Strategy>
0126 static inline return_type apply(Geometry const& geometry, Strategy const& strategy)
0127 {
0128 return calculate_null::apply<return_type>(geometry, strategy);
0129 }
0130 };
0131
0132
0133 template <typename Geometry>
0134 struct length<Geometry, linestring_tag>
0135 : detail::length::range_length<Geometry, closed>
0136 {};
0137
0138
0139
0140
0141
0142 template <typename Geometry>
0143 struct length<Geometry, segment_tag>
0144 : detail::length::segment_length<Geometry>
0145 {};
0146
0147
0148 template <typename MultiLinestring>
0149 struct length<MultiLinestring, multi_linestring_tag> : detail::multi_sum
0150 {
0151 template <typename Strategy>
0152 static inline typename default_length_result<MultiLinestring>::type
0153 apply(MultiLinestring const& multi, Strategy const& strategy)
0154 {
0155 return multi_sum::apply
0156 <
0157 typename default_length_result<MultiLinestring>::type,
0158 detail::length::range_length
0159 <
0160 typename boost::range_value<MultiLinestring>::type,
0161 closed
0162 >
0163 >(multi, strategy);
0164
0165 }
0166 };
0167
0168
0169 }
0170 #endif
0171
0172
0173 namespace resolve_strategy {
0174
0175 template
0176 <
0177 typename Strategies,
0178 bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
0179 >
0180 struct length
0181 {
0182 template <typename Geometry>
0183 static inline typename default_length_result<Geometry>::type
0184 apply(Geometry const& geometry, Strategies const& strategies)
0185 {
0186 return dispatch::length<Geometry>::apply(geometry, strategies);
0187 }
0188 };
0189
0190 template <typename Strategy>
0191 struct length<Strategy, false>
0192 {
0193 template <typename Geometry>
0194 static inline typename default_length_result<Geometry>::type
0195 apply(Geometry const& geometry, Strategy const& strategy)
0196 {
0197 using strategies::length::services::strategy_converter;
0198 return dispatch::length<Geometry>::apply(
0199 geometry, strategy_converter<Strategy>::get(strategy));
0200 }
0201 };
0202
0203 template <>
0204 struct length<default_strategy, false>
0205 {
0206 template <typename Geometry>
0207 static inline typename default_length_result<Geometry>::type
0208 apply(Geometry const& geometry, default_strategy const&)
0209 {
0210 typedef typename strategies::length::services::default_strategy
0211 <
0212 Geometry
0213 >::type strategies_type;
0214
0215 return dispatch::length<Geometry>::apply(geometry, strategies_type());
0216 }
0217 };
0218
0219 }
0220
0221
0222 namespace resolve_dynamic {
0223
0224 template <typename Geometry, typename Tag = typename geometry::tag<Geometry>::type>
0225 struct length
0226 {
0227 template <typename Strategy>
0228 static inline typename default_length_result<Geometry>::type
0229 apply(Geometry const& geometry, Strategy const& strategy)
0230 {
0231 return resolve_strategy::length<Strategy>::apply(geometry, strategy);
0232 }
0233 };
0234
0235 template <typename Geometry>
0236 struct length<Geometry, dynamic_geometry_tag>
0237 {
0238 template <typename Strategy>
0239 static inline typename default_length_result<Geometry>::type
0240 apply(Geometry const& geometry, Strategy const& strategy)
0241 {
0242 typename default_length_result<Geometry>::type result = 0;
0243 traits::visit<Geometry>::apply([&](auto const& g)
0244 {
0245 result = length<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
0246 }, geometry);
0247 return result;
0248 }
0249 };
0250
0251 template <typename Geometry>
0252 struct length<Geometry, geometry_collection_tag>
0253 {
0254 template <typename Strategy>
0255 static inline typename default_length_result<Geometry>::type
0256 apply(Geometry const& geometry, Strategy const& strategy)
0257 {
0258 typename default_length_result<Geometry>::type result = 0;
0259 detail::visit_breadth_first([&](auto const& g)
0260 {
0261 result += length<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
0262 return true;
0263 }, geometry);
0264 return result;
0265 }
0266 };
0267
0268 }
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282 template<typename Geometry>
0283 inline typename default_length_result<Geometry>::type
0284 length(Geometry const& geometry)
0285 {
0286 concepts::check<Geometry const>();
0287
0288
0289
0290 return resolve_dynamic::length<Geometry>::apply(geometry, default_strategy());
0291 }
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308 template<typename Geometry, typename Strategy>
0309 inline typename default_length_result<Geometry>::type
0310 length(Geometry const& geometry, Strategy const& strategy)
0311 {
0312 concepts::check<Geometry const>();
0313
0314
0315
0316 return resolve_dynamic::length<Geometry>::apply(geometry, strategy);
0317 }
0318
0319
0320 }}
0321
0322 #endif