File indexing completed on 2025-01-18 09:35:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP
0013 #define BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP
0014
0015
0016 #include <boost/range/size.hpp>
0017 #include <boost/range/value_type.hpp>
0018 #include <boost/throw_exception.hpp>
0019
0020 #include <boost/geometry/algorithms/clear.hpp>
0021 #include <boost/geometry/algorithms/convert.hpp>
0022 #include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
0023 #include <boost/geometry/algorithms/detail/visit.hpp>
0024 #include <boost/geometry/algorithms/not_implemented.hpp>
0025 #include <boost/geometry/core/closure.hpp>
0026 #include <boost/geometry/core/exception.hpp>
0027 #include <boost/geometry/core/tag.hpp>
0028 #include <boost/geometry/core/tags.hpp>
0029 #include <boost/geometry/core/visit.hpp>
0030 #include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
0031 #include <boost/geometry/strategies/default_strategy.hpp>
0032 #include <boost/geometry/strategies/densify/cartesian.hpp>
0033 #include <boost/geometry/strategies/densify/geographic.hpp>
0034 #include <boost/geometry/strategies/densify/spherical.hpp>
0035 #include <boost/geometry/strategies/detail.hpp>
0036 #include <boost/geometry/util/constexpr.hpp>
0037 #include <boost/geometry/util/range.hpp>
0038
0039
0040 namespace boost { namespace geometry
0041 {
0042
0043
0044 #ifndef DOXYGEN_NO_DETAIL
0045 namespace detail { namespace densify
0046 {
0047
0048 template <typename Range>
0049 struct push_back_policy
0050 {
0051 typedef typename boost::range_value<Range>::type point_type;
0052
0053 inline explicit push_back_policy(Range & rng)
0054 : m_rng(rng)
0055 {}
0056
0057 inline void apply(point_type const& p)
0058 {
0059 range::push_back(m_rng, p);
0060 }
0061
0062 private:
0063 Range & m_rng;
0064 };
0065
0066 template <typename Range, typename Point>
0067 inline void convert_and_push_back(Range & range, Point const& p)
0068 {
0069 typename boost::range_value<Range>::type p2;
0070 geometry::detail::conversion::convert_point_to_point(p, p2);
0071 range::push_back(range, p2);
0072 }
0073
0074 template <bool AppendLastPoint = true>
0075 struct densify_range
0076 {
0077 template <typename FwdRng, typename MutRng, typename T, typename Strategies>
0078 static inline void apply(FwdRng const& rng, MutRng & rng_out,
0079 T const& len, Strategies const& strategies)
0080 {
0081 typedef typename boost::range_value<FwdRng>::type point_t;
0082
0083 auto it = boost::begin(rng);
0084 auto const end = boost::end(rng);
0085
0086 if (it == end)
0087 {
0088 return;
0089 }
0090
0091 auto strategy = strategies.densify(rng);
0092 push_back_policy<MutRng> policy(rng_out);
0093
0094 auto prev = it;
0095 for ( ++it ; it != end ; prev = it++)
0096 {
0097 point_t const& p0 = *prev;
0098 point_t const& p1 = *it;
0099
0100 convert_and_push_back(rng_out, p0);
0101
0102 strategy.apply(p0, p1, policy, len);
0103 }
0104
0105 if BOOST_GEOMETRY_CONSTEXPR (AppendLastPoint)
0106 {
0107 convert_and_push_back(rng_out, *prev);
0108 }
0109 }
0110 };
0111
0112 template <bool IsClosed1, bool IsClosed2>
0113 struct densify_ring
0114 {
0115 template <typename Geometry, typename GeometryOut, typename T, typename Strategies>
0116 static inline void apply(Geometry const& ring, GeometryOut & ring_out,
0117 T const& len, Strategies const& strategies)
0118 {
0119 geometry::detail::densify::densify_range<true>
0120 ::apply(ring, ring_out, len, strategies);
0121
0122 if (boost::size(ring) <= 1)
0123 return;
0124
0125 auto const& p0 = range::back(ring);
0126 auto const& p1 = range::front(ring);
0127
0128 auto strategy = strategies.densify(ring);
0129 push_back_policy<GeometryOut> policy(ring_out);
0130
0131 strategy.apply(p0, p1, policy, len);
0132
0133 if BOOST_GEOMETRY_CONSTEXPR (IsClosed2)
0134 {
0135 convert_and_push_back(ring_out, p1);
0136 }
0137 }
0138 };
0139
0140 template <>
0141 struct densify_ring<true, true>
0142 : densify_range<true>
0143 {};
0144
0145 template <>
0146 struct densify_ring<true, false>
0147 : densify_range<false>
0148 {};
0149
0150 struct densify_convert
0151 {
0152 template <typename GeometryIn, typename GeometryOut, typename T, typename Strategy>
0153 static void apply(GeometryIn const& in, GeometryOut &out,
0154 T const& , Strategy const& )
0155 {
0156 geometry::convert(in, out);
0157 }
0158 };
0159
0160 }}
0161 #endif
0162
0163
0164 #ifndef DOXYGEN_NO_DISPATCH
0165 namespace dispatch
0166 {
0167
0168
0169 template
0170 <
0171 typename Geometry,
0172 typename GeometryOut,
0173 typename Tag1 = typename tag<Geometry>::type,
0174 typename Tag2 = typename tag<GeometryOut>::type
0175 >
0176 struct densify
0177 : not_implemented<Tag1, Tag2>
0178 {};
0179
0180 template <typename Geometry, typename GeometryOut>
0181 struct densify<Geometry, GeometryOut, point_tag, point_tag>
0182 : geometry::detail::densify::densify_convert
0183 {};
0184
0185 template <typename Geometry, typename GeometryOut>
0186 struct densify<Geometry, GeometryOut, segment_tag, segment_tag>
0187 : geometry::detail::densify::densify_convert
0188 {};
0189
0190 template <typename Geometry, typename GeometryOut>
0191 struct densify<Geometry, GeometryOut, box_tag, box_tag>
0192 : geometry::detail::densify::densify_convert
0193 {};
0194
0195 template <typename Geometry, typename GeometryOut>
0196 struct densify<Geometry, GeometryOut, multi_point_tag, multi_point_tag>
0197 : geometry::detail::densify::densify_convert
0198 {};
0199
0200 template <typename Geometry, typename GeometryOut>
0201 struct densify<Geometry, GeometryOut, linestring_tag, linestring_tag>
0202 : geometry::detail::densify::densify_range<>
0203 {};
0204
0205 template <typename Geometry, typename GeometryOut>
0206 struct densify<Geometry, GeometryOut, multi_linestring_tag, multi_linestring_tag>
0207 {
0208 template <typename T, typename Strategy>
0209 static void apply(Geometry const& mls, GeometryOut & mls_out,
0210 T const& len, Strategy const& strategy)
0211 {
0212 std::size_t count = boost::size(mls);
0213 range::resize(mls_out, count);
0214
0215 for (std::size_t i = 0 ; i < count ; ++i)
0216 {
0217 geometry::detail::densify::densify_range<>
0218 ::apply(range::at(mls, i), range::at(mls_out, i),
0219 len, strategy);
0220 }
0221 }
0222 };
0223
0224 template <typename Geometry, typename GeometryOut>
0225 struct densify<Geometry, GeometryOut, ring_tag, ring_tag>
0226 : geometry::detail::densify::densify_ring
0227 <
0228 geometry::closure<Geometry>::value != geometry::open,
0229 geometry::closure<GeometryOut>::value != geometry::open
0230 >
0231 {};
0232
0233 template <typename Geometry, typename GeometryOut>
0234 struct densify<Geometry, GeometryOut, polygon_tag, polygon_tag>
0235 {
0236 template <typename T, typename Strategy>
0237 static void apply(Geometry const& poly, GeometryOut & poly_out,
0238 T const& len, Strategy const& strategy)
0239 {
0240 apply_ring(exterior_ring(poly), exterior_ring(poly_out),
0241 len, strategy);
0242
0243 std::size_t count = boost::size(interior_rings(poly));
0244 range::resize(interior_rings(poly_out), count);
0245
0246 for (std::size_t i = 0 ; i < count ; ++i)
0247 {
0248 apply_ring(range::at(interior_rings(poly), i),
0249 range::at(interior_rings(poly_out), i),
0250 len, strategy);
0251 }
0252 }
0253
0254 template <typename Ring, typename RingOut, typename T, typename Strategy>
0255 static void apply_ring(Ring const& ring, RingOut & ring_out,
0256 T const& len, Strategy const& strategy)
0257 {
0258 densify<Ring, RingOut, ring_tag, ring_tag>
0259 ::apply(ring, ring_out, len, strategy);
0260 }
0261 };
0262
0263 template <typename Geometry, typename GeometryOut>
0264 struct densify<Geometry, GeometryOut, multi_polygon_tag, multi_polygon_tag>
0265 {
0266 template <typename T, typename Strategy>
0267 static void apply(Geometry const& mpoly, GeometryOut & mpoly_out,
0268 T const& len, Strategy const& strategy)
0269 {
0270 std::size_t count = boost::size(mpoly);
0271 range::resize(mpoly_out, count);
0272
0273 for (std::size_t i = 0 ; i < count ; ++i)
0274 {
0275 apply_poly(range::at(mpoly, i),
0276 range::at(mpoly_out, i),
0277 len, strategy);
0278 }
0279 }
0280
0281 template <typename Poly, typename PolyOut, typename T, typename Strategy>
0282 static void apply_poly(Poly const& poly, PolyOut & poly_out,
0283 T const& len, Strategy const& strategy)
0284 {
0285 densify<Poly, PolyOut, polygon_tag, polygon_tag>::
0286 apply(poly, poly_out, len, strategy);
0287 }
0288 };
0289
0290
0291 }
0292 #endif
0293
0294
0295 namespace resolve_strategy
0296 {
0297
0298 template
0299 <
0300 typename Strategies,
0301 bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
0302 >
0303 struct densify
0304 {
0305 template <typename Geometry, typename Distance>
0306 static inline void apply(Geometry const& geometry,
0307 Geometry& out,
0308 Distance const& max_distance,
0309 Strategies const& strategies)
0310 {
0311 dispatch::densify
0312 <
0313 Geometry, Geometry
0314 >::apply(geometry, out, max_distance, strategies);
0315 }
0316 };
0317
0318 template <typename Strategy>
0319 struct densify<Strategy, false>
0320 {
0321 template <typename Geometry, typename Distance>
0322 static inline void apply(Geometry const& geometry,
0323 Geometry& out,
0324 Distance const& max_distance,
0325 Strategy const& strategy)
0326 {
0327 using strategies::densify::services::strategy_converter;
0328
0329 dispatch::densify
0330 <
0331 Geometry, Geometry
0332 >::apply(geometry, out, max_distance,
0333 strategy_converter<Strategy>::get(strategy));
0334 }
0335 };
0336
0337 template <>
0338 struct densify<default_strategy, false>
0339 {
0340 template <typename Geometry, typename Distance>
0341 static inline void apply(Geometry const& geometry,
0342 Geometry& out,
0343 Distance const& max_distance,
0344 default_strategy const&)
0345 {
0346 typedef typename strategies::densify::services::default_strategy
0347 <
0348 Geometry
0349 >::type strategies_type;
0350
0351 dispatch::densify
0352 <
0353 Geometry, Geometry
0354 >::apply(geometry, out, max_distance, strategies_type());
0355 }
0356 };
0357
0358 }
0359
0360
0361 namespace resolve_dynamic {
0362
0363 template <typename Geometry, typename Tag = typename tag<Geometry>::type>
0364 struct densify
0365 {
0366 template <typename Distance, typename Strategy>
0367 static inline void apply(Geometry const& geometry,
0368 Geometry& out,
0369 Distance const& max_distance,
0370 Strategy const& strategy)
0371 {
0372 resolve_strategy::densify
0373 <
0374 Strategy
0375 >::apply(geometry, out, max_distance, strategy);
0376 }
0377 };
0378
0379 template <typename Geometry>
0380 struct densify<Geometry, dynamic_geometry_tag>
0381 {
0382 template <typename Distance, typename Strategy>
0383 static inline void
0384 apply(Geometry const& geometry,
0385 Geometry& out,
0386 Distance const& max_distance,
0387 Strategy const& strategy)
0388 {
0389 traits::visit<Geometry>::apply([&](auto const& g)
0390 {
0391 using geom_t = util::remove_cref_t<decltype(g)>;
0392 geom_t o;
0393 densify<geom_t>::apply(g, o, max_distance, strategy);
0394 out = std::move(o);
0395 }, geometry);
0396 }
0397 };
0398
0399 template <typename Geometry>
0400 struct densify<Geometry, geometry_collection_tag>
0401 {
0402 template <typename Distance, typename Strategy>
0403 static inline void
0404 apply(Geometry const& geometry,
0405 Geometry& out,
0406 Distance const& max_distance,
0407 Strategy const& strategy)
0408 {
0409 detail::visit_breadth_first([&](auto const& g)
0410 {
0411 using geom_t = util::remove_cref_t<decltype(g)>;
0412 geom_t o;
0413 densify<geom_t>::apply(g, o, max_distance, strategy);
0414 traits::emplace_back<Geometry>::apply(out, std::move(o));
0415 return true;
0416 }, geometry);
0417 }
0418 };
0419
0420 }
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451 template <typename Geometry, typename Distance, typename Strategy>
0452 inline void densify(Geometry const& geometry,
0453 Geometry& out,
0454 Distance const& max_distance,
0455 Strategy const& strategy)
0456 {
0457 concepts::check<Geometry>();
0458
0459 if (max_distance <= Distance(0))
0460 {
0461 BOOST_THROW_EXCEPTION(geometry::invalid_input_exception());
0462 }
0463
0464 geometry::clear(out);
0465
0466 resolve_dynamic::densify
0467 <
0468 Geometry
0469 >::apply(geometry, out, max_distance, strategy);
0470 }
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493 template <typename Geometry, typename Distance>
0494 inline void densify(Geometry const& geometry,
0495 Geometry& out,
0496 Distance const& max_distance)
0497 {
0498 densify(geometry, out, max_distance, default_strategy());
0499 }
0500
0501
0502 }}
0503
0504 #endif