File indexing completed on 2025-09-17 08:30:48
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 point_type_t<Segment> p1, p2;
0068 geometry::detail::assign_point_from_index<0>(segment, p1);
0069 geometry::detail::assign_point_from_index<1>(segment, p2);
0070 return strategies.distance(p1, p2).apply(p1, p2);
0071 }
0072 };
0073
0074
0075
0076
0077
0078
0079
0080 template<typename Range, closure_selector Closure>
0081 struct range_length
0082 {
0083 typedef typename default_length_result<Range>::type return_type;
0084
0085 template <typename Strategies>
0086 static inline return_type
0087 apply(Range const& range, Strategies const& strategies)
0088 {
0089 return_type sum = return_type();
0090 detail::closed_view<Range const> const view(range);
0091 auto it = boost::begin(view);
0092 auto const end = boost::end(view);
0093 if (it != end)
0094 {
0095 auto const strategy = strategies.distance(dummy_point(), dummy_point());
0096
0097 for(auto previous = it++; it != end; ++previous, ++it)
0098 {
0099
0100
0101 sum += strategy.apply(*previous, *it);
0102 }
0103 }
0104
0105 return sum;
0106 }
0107 };
0108
0109
0110 }}
0111 #endif
0112
0113
0114 #ifndef DOXYGEN_NO_DISPATCH
0115 namespace dispatch
0116 {
0117
0118
0119 template <typename Geometry, typename Tag = tag_t<Geometry>>
0120 struct length : detail::calculate_null
0121 {
0122 typedef typename default_length_result<Geometry>::type return_type;
0123
0124 template <typename Strategy>
0125 static inline return_type apply(Geometry const& geometry, Strategy const& strategy)
0126 {
0127 return calculate_null::apply<return_type>(geometry, strategy);
0128 }
0129 };
0130
0131
0132 template <typename Geometry>
0133 struct length<Geometry, linestring_tag>
0134 : detail::length::range_length<Geometry, closed>
0135 {};
0136
0137
0138
0139
0140
0141 template <typename Geometry>
0142 struct length<Geometry, segment_tag>
0143 : detail::length::segment_length<Geometry>
0144 {};
0145
0146
0147 template <typename MultiLinestring>
0148 struct length<MultiLinestring, multi_linestring_tag> : detail::multi_sum
0149 {
0150 template <typename Strategy>
0151 static inline typename default_length_result<MultiLinestring>::type
0152 apply(MultiLinestring const& multi, Strategy const& strategy)
0153 {
0154 return multi_sum::apply
0155 <
0156 typename default_length_result<MultiLinestring>::type,
0157 detail::length::range_length
0158 <
0159 typename boost::range_value<MultiLinestring>::type,
0160 closed
0161 >
0162 >(multi, strategy);
0163
0164 }
0165 };
0166
0167
0168 }
0169 #endif
0170
0171
0172 namespace resolve_strategy {
0173
0174 template
0175 <
0176 typename Strategies,
0177 bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
0178 >
0179 struct length
0180 {
0181 template <typename Geometry>
0182 static inline typename default_length_result<Geometry>::type
0183 apply(Geometry const& geometry, Strategies const& strategies)
0184 {
0185 return dispatch::length<Geometry>::apply(geometry, strategies);
0186 }
0187 };
0188
0189 template <typename Strategy>
0190 struct length<Strategy, false>
0191 {
0192 template <typename Geometry>
0193 static inline typename default_length_result<Geometry>::type
0194 apply(Geometry const& geometry, Strategy const& strategy)
0195 {
0196 using strategies::length::services::strategy_converter;
0197 return dispatch::length<Geometry>::apply(
0198 geometry, strategy_converter<Strategy>::get(strategy));
0199 }
0200 };
0201
0202 template <>
0203 struct length<default_strategy, false>
0204 {
0205 template <typename Geometry>
0206 static inline typename default_length_result<Geometry>::type
0207 apply(Geometry const& geometry, default_strategy const&)
0208 {
0209 typedef typename strategies::length::services::default_strategy
0210 <
0211 Geometry
0212 >::type strategies_type;
0213
0214 return dispatch::length<Geometry>::apply(geometry, strategies_type());
0215 }
0216 };
0217
0218 }
0219
0220
0221 namespace resolve_dynamic {
0222
0223 template <typename Geometry, typename Tag = geometry::tag_t<Geometry>>
0224 struct length
0225 {
0226 template <typename Strategy>
0227 static inline typename default_length_result<Geometry>::type
0228 apply(Geometry const& geometry, Strategy const& strategy)
0229 {
0230 return resolve_strategy::length<Strategy>::apply(geometry, strategy);
0231 }
0232 };
0233
0234 template <typename Geometry>
0235 struct length<Geometry, dynamic_geometry_tag>
0236 {
0237 template <typename Strategy>
0238 static inline typename default_length_result<Geometry>::type
0239 apply(Geometry const& geometry, Strategy const& strategy)
0240 {
0241 typename default_length_result<Geometry>::type result = 0;
0242 traits::visit<Geometry>::apply([&](auto const& g)
0243 {
0244 result = length<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
0245 }, geometry);
0246 return result;
0247 }
0248 };
0249
0250 template <typename Geometry>
0251 struct length<Geometry, geometry_collection_tag>
0252 {
0253 template <typename Strategy>
0254 static inline typename default_length_result<Geometry>::type
0255 apply(Geometry const& geometry, Strategy const& strategy)
0256 {
0257 typename default_length_result<Geometry>::type result = 0;
0258 detail::visit_breadth_first([&](auto const& g)
0259 {
0260 result += length<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
0261 return true;
0262 }, geometry);
0263 return result;
0264 }
0265 };
0266
0267 }
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281 template<typename Geometry>
0282 inline typename default_length_result<Geometry>::type
0283 length(Geometry const& geometry)
0284 {
0285 concepts::check<Geometry const>();
0286
0287
0288
0289 return resolve_dynamic::length<Geometry>::apply(geometry, default_strategy());
0290 }
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307 template<typename Geometry, typename Strategy>
0308 inline typename default_length_result<Geometry>::type
0309 length(Geometry const& geometry, Strategy const& strategy)
0310 {
0311 concepts::check<Geometry const>();
0312
0313
0314
0315 return resolve_dynamic::length<Geometry>::apply(geometry, strategy);
0316 }
0317
0318
0319 }}
0320
0321 #endif