File indexing completed on 2025-01-18 09:36:45
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_JOIN_ROUND_HPP
0011 #define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_JOIN_ROUND_HPP
0012
0013 #include <boost/range/value_type.hpp>
0014
0015 #include <boost/geometry/core/radian_access.hpp>
0016
0017 #include <boost/geometry/srs/spheroid.hpp>
0018 #include <boost/geometry/strategies/buffer.hpp>
0019 #include <boost/geometry/strategies/geographic/buffer_helper.hpp>
0020 #include <boost/geometry/strategies/geographic/parameters.hpp>
0021 #include <boost/geometry/util/math.hpp>
0022 #include <boost/geometry/util/select_calculation_type.hpp>
0023
0024
0025 namespace boost { namespace geometry
0026 {
0027
0028 namespace strategy { namespace buffer
0029 {
0030
0031 template
0032 <
0033 typename FormulaPolicy = strategy::andoyer,
0034 typename Spheroid = srs::spheroid<double>,
0035 typename CalculationType = void
0036 >
0037 class geographic_join_round
0038 {
0039 public :
0040
0041
0042
0043
0044 explicit inline geographic_join_round(Spheroid const& spheroid,
0045 std::size_t points_per_circle = default_points_per_circle)
0046 : m_spheroid(spheroid)
0047 , m_points_per_circle(get_point_count_for_join(points_per_circle))
0048 {}
0049
0050
0051
0052 explicit inline geographic_join_round(std::size_t points_per_circle = default_points_per_circle)
0053 : m_points_per_circle(get_point_count_for_join(points_per_circle))
0054 {}
0055
0056 #ifndef DOXYGEN_SHOULD_SKIP_THIS
0057
0058 template <typename Point, typename DistanceType, typename RangeOut>
0059 inline bool apply(Point const& , Point const& vertex,
0060 Point const& perp1, Point const& perp2,
0061 DistanceType const& buffer_distance,
0062 RangeOut& range_out) const
0063 {
0064 using calc_t = typename select_calculation_type
0065 <
0066 Point,
0067 typename boost::range_value<RangeOut>::type,
0068 CalculationType
0069 >::type;
0070
0071 using helper = geographic_buffer_helper<FormulaPolicy, calc_t>;
0072
0073 calc_t const lon_rad = get_as_radian<0>(vertex);
0074 calc_t const lat_rad = get_as_radian<1>(vertex);
0075
0076 calc_t first_azimuth;
0077 calc_t angle_diff;
0078 if (! helper::calculate_angles(lon_rad, lat_rad, perp1, perp2, m_spheroid,
0079 angle_diff, first_azimuth))
0080 {
0081 return false;
0082 }
0083
0084 static calc_t const two_pi = geometry::math::two_pi<calc_t>();
0085 calc_t const circle_fraction = angle_diff / two_pi;
0086 std::size_t const n = (std::max)(static_cast<std::size_t>(
0087 std::ceil(m_points_per_circle * circle_fraction)), std::size_t(1));
0088
0089 calc_t const diff = angle_diff / static_cast<calc_t>(n);
0090 calc_t azi = math::wrap_azimuth_in_radian(first_azimuth + diff);
0091
0092 range_out.push_back(perp1);
0093
0094
0095
0096 for (std::size_t i = 1; i < n; i++)
0097 {
0098 helper::append_point(lon_rad, lat_rad, buffer_distance, azi, m_spheroid, range_out);
0099 azi = math::wrap_azimuth_in_radian(azi + diff);
0100 }
0101
0102 range_out.push_back(perp2);
0103 return true;
0104 }
0105
0106 template <typename NumericType>
0107 static inline NumericType max_distance(NumericType const& distance)
0108 {
0109 return distance;
0110 }
0111
0112 #endif
0113
0114 private :
0115 Spheroid m_spheroid;
0116 std::size_t m_points_per_circle;
0117 };
0118
0119 }}
0120
0121 }}
0122
0123 #endif