buffer_join_round.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // Boost.Geometry
  2. // Copyright (c) 2022 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
  4. // Use, modification and distribution is subject to the Boost Software License,
  5. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_JOIN_ROUND_HPP
  8. #define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_JOIN_ROUND_HPP
  9. #include <boost/range/value_type.hpp>
  10. #include <boost/geometry/core/radian_access.hpp>
  11. #include <boost/geometry/srs/spheroid.hpp>
  12. #include <boost/geometry/strategies/buffer.hpp>
  13. #include <boost/geometry/strategies/geographic/buffer_helper.hpp>
  14. #include <boost/geometry/strategies/geographic/parameters.hpp>
  15. #include <boost/geometry/util/math.hpp>
  16. #include <boost/geometry/util/select_calculation_type.hpp>
  17. namespace boost { namespace geometry
  18. {
  19. namespace strategy { namespace buffer
  20. {
  21. template
  22. <
  23. typename FormulaPolicy = strategy::andoyer,
  24. typename Spheroid = srs::spheroid<double>,
  25. typename CalculationType = void
  26. >
  27. class geographic_join_round
  28. {
  29. public :
  30. //! \brief Constructs the strategy with a spheroid
  31. //! \param spheroid The spheroid to be used
  32. //! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
  33. explicit inline geographic_join_round(Spheroid const& spheroid,
  34. std::size_t points_per_circle = default_points_per_circle)
  35. : m_spheroid(spheroid)
  36. , m_points_per_circle(get_point_count_for_join(points_per_circle))
  37. {}
  38. //! \brief Constructs the strategy
  39. //! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
  40. explicit inline geographic_join_round(std::size_t points_per_circle = default_points_per_circle)
  41. : m_points_per_circle(get_point_count_for_join(points_per_circle))
  42. {}
  43. #ifndef DOXYGEN_SHOULD_SKIP_THIS
  44. //! Fills output_range with a rounded shape around a vertex
  45. template <typename Point, typename DistanceType, typename RangeOut>
  46. inline bool apply(Point const& /*ip*/, Point const& vertex,
  47. Point const& perp1, Point const& perp2,
  48. DistanceType const& buffer_distance,
  49. RangeOut& range_out) const
  50. {
  51. using calc_t = typename select_calculation_type
  52. <
  53. Point,
  54. typename boost::range_value<RangeOut>::type,
  55. CalculationType
  56. >::type;
  57. using helper = geographic_buffer_helper<FormulaPolicy, calc_t>;
  58. calc_t const lon_rad = get_as_radian<0>(vertex);
  59. calc_t const lat_rad = get_as_radian<1>(vertex);
  60. calc_t first_azimuth;
  61. calc_t angle_diff;
  62. if (! helper::calculate_angles(lon_rad, lat_rad, perp1, perp2, m_spheroid,
  63. angle_diff, first_azimuth))
  64. {
  65. return false;
  66. }
  67. static calc_t const two_pi = geometry::math::two_pi<calc_t>();
  68. calc_t const circle_fraction = angle_diff / two_pi;
  69. std::size_t const n = (std::max)(static_cast<std::size_t>(
  70. std::ceil(m_points_per_circle * circle_fraction)), std::size_t(1));
  71. calc_t const diff = angle_diff / static_cast<calc_t>(n);
  72. calc_t azi = math::wrap_azimuth_in_radian(first_azimuth + diff);
  73. range_out.push_back(perp1);
  74. // Generate points between 0 and n, not including them
  75. // because perp1 and perp2 are inserted before and after this range.
  76. for (std::size_t i = 1; i < n; i++)
  77. {
  78. helper::append_point(lon_rad, lat_rad, buffer_distance, azi, m_spheroid, range_out);
  79. azi = math::wrap_azimuth_in_radian(azi + diff);
  80. }
  81. range_out.push_back(perp2);
  82. return true;
  83. }
  84. template <typename NumericType>
  85. static inline NumericType max_distance(NumericType const& distance)
  86. {
  87. return distance;
  88. }
  89. #endif // DOXYGEN_SHOULD_SKIP_THIS
  90. private :
  91. Spheroid m_spheroid;
  92. std::size_t m_points_per_circle;
  93. };
  94. }} // namespace strategy::buffer
  95. }} // namespace boost::geometry
  96. #endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_JOIN_ROUND_HPP