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_PERIMETER_HPP
0021 #define BOOST_GEOMETRY_ALGORITHMS_PERIMETER_HPP
0022
0023 #include <boost/range/value_type.hpp>
0024
0025 #include <boost/geometry/algorithms/length.hpp>
0026 #include <boost/geometry/algorithms/detail/calculate_null.hpp>
0027 #include <boost/geometry/algorithms/detail/calculate_sum.hpp>
0028 #include <boost/geometry/algorithms/detail/multi_sum.hpp>
0029
0030 #include <boost/geometry/algorithms/detail/visit.hpp>
0031
0032 #include <boost/geometry/core/closure.hpp>
0033 #include <boost/geometry/core/tags.hpp>
0034 #include <boost/geometry/core/visit.hpp>
0035
0036 #include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
0037 #include <boost/geometry/geometries/concepts/check.hpp>
0038
0039 #include <boost/geometry/strategies/default_length_result.hpp>
0040 #include <boost/geometry/strategies/default_strategy.hpp>
0041 #include <boost/geometry/strategies/detail.hpp>
0042 #include <boost/geometry/strategies/length/cartesian.hpp>
0043 #include <boost/geometry/strategies/length/geographic.hpp>
0044 #include <boost/geometry/strategies/length/spherical.hpp>
0045
0046 namespace boost { namespace geometry
0047 {
0048
0049 #ifndef DOXYGEN_NO_DISPATCH
0050 namespace dispatch
0051 {
0052
0053
0054 template <typename Geometry, typename Tag = typename tag<Geometry>::type>
0055 struct perimeter : detail::calculate_null
0056 {
0057 typedef typename default_length_result<Geometry>::type return_type;
0058
0059 template <typename Strategy>
0060 static inline return_type apply(Geometry const& geometry, Strategy const& strategy)
0061 {
0062 return calculate_null::apply<return_type>(geometry, strategy);
0063 }
0064 };
0065
0066 template <typename Geometry>
0067 struct perimeter<Geometry, ring_tag>
0068 : detail::length::range_length
0069 <
0070 Geometry,
0071 closure<Geometry>::value
0072 >
0073 {};
0074
0075 template <typename Polygon>
0076 struct perimeter<Polygon, polygon_tag> : detail::calculate_polygon_sum
0077 {
0078 typedef typename default_length_result<Polygon>::type return_type;
0079 typedef detail::length::range_length
0080 <
0081 typename ring_type<Polygon>::type,
0082 closure<Polygon>::value
0083 > policy;
0084
0085 template <typename Strategy>
0086 static inline return_type apply(Polygon const& polygon, Strategy const& strategy)
0087 {
0088 return calculate_polygon_sum::apply<return_type, policy>(polygon, strategy);
0089 }
0090 };
0091
0092 template <typename MultiPolygon>
0093 struct perimeter<MultiPolygon, multi_polygon_tag> : detail::multi_sum
0094 {
0095 typedef typename default_length_result<MultiPolygon>::type return_type;
0096
0097 template <typename Strategy>
0098 static inline return_type apply(MultiPolygon const& multi, Strategy const& strategy)
0099 {
0100 return multi_sum::apply
0101 <
0102 return_type,
0103 perimeter<typename boost::range_value<MultiPolygon>::type>
0104 >(multi, strategy);
0105 }
0106 };
0107
0108
0109
0110
0111 }
0112 #endif
0113
0114
0115 namespace resolve_strategy {
0116
0117 template
0118 <
0119 typename Strategies,
0120 bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
0121 >
0122 struct perimeter
0123 {
0124 template <typename Geometry>
0125 static inline typename default_length_result<Geometry>::type
0126 apply(Geometry const& geometry, Strategies const& strategies)
0127 {
0128 return dispatch::perimeter<Geometry>::apply(geometry, strategies);
0129 }
0130 };
0131
0132 template <typename Strategy>
0133 struct perimeter<Strategy, false>
0134 {
0135 template <typename Geometry>
0136 static inline typename default_length_result<Geometry>::type
0137 apply(Geometry const& geometry, Strategy const& strategy)
0138 {
0139 using strategies::length::services::strategy_converter;
0140 return dispatch::perimeter<Geometry>::apply(
0141 geometry, strategy_converter<Strategy>::get(strategy));
0142 }
0143 };
0144
0145 template <>
0146 struct perimeter<default_strategy, false>
0147 {
0148 template <typename Geometry>
0149 static inline typename default_length_result<Geometry>::type
0150 apply(Geometry const& geometry, default_strategy const&)
0151 {
0152 typedef typename strategies::length::services::default_strategy
0153 <
0154 Geometry
0155 >::type strategies_type;
0156
0157 return dispatch::perimeter<Geometry>::apply(geometry, strategies_type());
0158 }
0159 };
0160
0161 }
0162
0163
0164 namespace resolve_dynamic {
0165
0166 template <typename Geometry, typename Tag = typename geometry::tag<Geometry>::type>
0167 struct perimeter
0168 {
0169 template <typename Strategy>
0170 static inline typename default_length_result<Geometry>::type
0171 apply(Geometry const& geometry, Strategy const& strategy)
0172 {
0173 concepts::check<Geometry const>();
0174 return resolve_strategy::perimeter<Strategy>::apply(geometry, strategy);
0175 }
0176 };
0177
0178 template <typename Geometry>
0179 struct perimeter<Geometry, dynamic_geometry_tag>
0180 {
0181 template <typename Strategy>
0182 static inline typename default_length_result<Geometry>::type
0183 apply(Geometry const& geometry, Strategy const& strategy)
0184 {
0185 typename default_length_result<Geometry>::type result = 0;
0186 traits::visit<Geometry>::apply([&](auto const& g)
0187 {
0188 result = perimeter<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
0189 }, geometry);
0190 return result;
0191 }
0192 };
0193
0194 template <typename Geometry>
0195 struct perimeter<Geometry, geometry_collection_tag>
0196 {
0197 template <typename Strategy>
0198 static inline typename default_length_result<Geometry>::type
0199 apply(Geometry const& geometry, Strategy const& strategy)
0200 {
0201 typename default_length_result<Geometry>::type result = 0;
0202 detail::visit_breadth_first([&](auto const& g)
0203 {
0204 result += perimeter<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
0205 return true;
0206 }, geometry);
0207 return result;
0208 }
0209 };
0210
0211 }
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230 template<typename Geometry>
0231 inline typename default_length_result<Geometry>::type perimeter(
0232 Geometry const& geometry)
0233 {
0234
0235 return resolve_dynamic::perimeter<Geometry>::apply(geometry, default_strategy());
0236 }
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252 template<typename Geometry, typename Strategy>
0253 inline typename default_length_result<Geometry>::type perimeter(
0254 Geometry const& geometry, Strategy const& strategy)
0255 {
0256
0257 return resolve_dynamic::perimeter<Geometry>::apply(geometry, strategy);
0258 }
0259
0260 }}
0261
0262 #endif
0263