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