buffer_side_straight.hpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Boost.Geometry
  2. // Copyright (c) 2022 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Use, modification and distribution is subject to the Boost Software License,
  4. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_SIDE_STRAIGHT_HPP
  7. #define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_SIDE_STRAIGHT_HPP
  8. #include <cstddef>
  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. /*!
  22. \brief Create a straight buffer along a side, on the Earth
  23. \ingroup strategies
  24. \details This strategy can be used as SideStrategy for the buffer algorithm.
  25. */
  26. template
  27. <
  28. typename FormulaPolicy = strategy::andoyer,
  29. typename Spheroid = srs::spheroid<double>,
  30. typename CalculationType = void
  31. >
  32. class geographic_side_straight
  33. {
  34. public :
  35. //! \brief Constructs the strategy with a spheroid
  36. //! \param spheroid The spheroid to be used
  37. explicit inline geographic_side_straight(Spheroid const& spheroid)
  38. : m_spheroid(spheroid)
  39. {}
  40. //! \brief Constructs the strategy
  41. inline geographic_side_straight()
  42. {}
  43. #ifndef DOXYGEN_SHOULD_SKIP_THIS
  44. // Returns true if the buffer distance is always the same
  45. static inline bool equidistant()
  46. {
  47. return true;
  48. }
  49. template
  50. <
  51. typename Point,
  52. typename DistanceStrategy,
  53. typename RangeOut
  54. >
  55. inline result_code apply(Point const& input_p1, Point const& input_p2,
  56. buffer_side_selector side,
  57. DistanceStrategy const& distance_strategy,
  58. RangeOut& range_out) const
  59. {
  60. using calc_t = typename select_calculation_type
  61. <
  62. Point,
  63. typename boost::range_value<RangeOut>::type,
  64. CalculationType
  65. >::type;
  66. using helper = geographic_buffer_helper<FormulaPolicy, calc_t>;
  67. calc_t const lon1_rad = get_as_radian<0>(input_p1);
  68. calc_t const lat1_rad = get_as_radian<1>(input_p1);
  69. calc_t const lon2_rad = get_as_radian<0>(input_p2);
  70. calc_t const lat2_rad = get_as_radian<1>(input_p2);
  71. if (lon1_rad == lon2_rad && lat1_rad == lat2_rad)
  72. {
  73. // Coordinates are simplified and therefore most often not equal.
  74. // But if simplify is skipped, or for lines with two
  75. // equal points, length is 0 and we cannot generate output.
  76. return result_no_output;
  77. }
  78. // Measure the angle from p1 to p2 with the Inverse transformation,
  79. // and subtract pi/2 to make it perpendicular.
  80. auto const inv = helper::azimuth(lon1_rad, lat1_rad, input_p2, m_spheroid);
  81. auto const angle = math::wrap_azimuth_in_radian(inv - geometry::math::half_pi<calc_t>());
  82. // Calculate the distance and generate two points at that distance
  83. auto const distance = distance_strategy.apply(input_p1, input_p2, side);
  84. helper::append_point(lon1_rad, lat1_rad, distance, angle, m_spheroid, range_out);
  85. helper::append_point(lon2_rad, lat2_rad, distance, angle, m_spheroid, range_out);
  86. return result_normal;
  87. }
  88. #endif // DOXYGEN_SHOULD_SKIP_THIS
  89. private :
  90. Spheroid m_spheroid;
  91. };
  92. }} // namespace strategy::buffer
  93. }} // namespace boost::geometry
  94. #endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_SIDE_STRAIGHT_HPP