Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:36:45

0001 // Boost.Geometry
0002 
0003 // Copyright (c) 2022 Barend Gehrels, Amsterdam, the Netherlands.
0004 
0005 // Use, modification and distribution is subject to the Boost Software License,
0006 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt)
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     //! \brief Constructs the strategy with a spheroid
0041     //! \param spheroid The spheroid to be used
0042     //! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
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     //! \brief Constructs the strategy
0050     //! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
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     //! Fills output_range with a sharp shape around a vertex
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             // It is opposite, perp1==perp2, do not generate a miter cap
0092             return false;
0093         }
0094 
0095         // If it is sharp (angle close to 0), the distance will become too high and will be capped.
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 // DOXYGEN_SHOULD_SKIP_THIS
0112 
0113 private :
0114     double valid_limit(double miter_limit) const
0115     {
0116         if (miter_limit < 1.0)
0117         {
0118             // It should always exceed the buffer distance
0119             miter_limit = 1.0;
0120         }
0121         return miter_limit;
0122     }
0123 
0124     Spheroid m_spheroid;
0125     double m_miter_limit;
0126 };
0127 
0128 }} // namespace strategy::buffer
0129 
0130 }} // namespace boost::geometry
0131 
0132 #endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_JOIN_MITER_HPP