File indexing completed on 2025-01-18 09:36:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP
0016 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_JOIN_ROUND_HPP
0017
0018 #include <algorithm>
0019
0020 #include <boost/geometry/core/cs.hpp>
0021 #include <boost/geometry/policies/compare.hpp>
0022 #include <boost/geometry/strategies/buffer.hpp>
0023 #include <boost/geometry/util/math.hpp>
0024 #include <boost/geometry/util/select_most_precise.hpp>
0025
0026 #ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
0027 #include <iostream>
0028 #include <boost/geometry/io/wkt/wkt.hpp>
0029 #endif
0030
0031
0032 namespace boost { namespace geometry
0033 {
0034
0035
0036 namespace strategy { namespace buffer
0037 {
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 class join_round
0058 {
0059 public :
0060
0061
0062
0063 explicit inline join_round(std::size_t points_per_circle = default_points_per_circle)
0064 : m_points_per_circle(get_point_count_for_join(points_per_circle))
0065 {}
0066
0067 private :
0068 template
0069 <
0070 typename PromotedType,
0071 typename Point,
0072 typename DistanceType,
0073 typename RangeOut
0074 >
0075 inline void generate_points(Point const& vertex,
0076 Point const& perp1, Point const& perp2,
0077 DistanceType const& buffer_distance,
0078 RangeOut& range_out) const
0079 {
0080 PromotedType const dx1 = get<0>(perp1) - get<0>(vertex);
0081 PromotedType const dy1 = get<1>(perp1) - get<1>(vertex);
0082 PromotedType const dx2 = get<0>(perp2) - get<0>(vertex);
0083 PromotedType const dy2 = get<1>(perp2) - get<1>(vertex);
0084
0085 PromotedType const two_pi = geometry::math::two_pi<PromotedType>();
0086
0087 PromotedType const angle1 = atan2(dy1, dx1);
0088 PromotedType angle2 = atan2(dy2, dx2);
0089 while (angle2 > angle1)
0090 {
0091 angle2 -= two_pi;
0092 }
0093 PromotedType const angle_diff = angle1 - angle2;
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 std::size_t const n = (std::max)(static_cast<std::size_t>(
0105 ceil(m_points_per_circle * angle_diff / two_pi)), std::size_t(1));
0106
0107 PromotedType const diff = angle_diff / static_cast<PromotedType>(n);
0108 PromotedType a = angle1 - diff;
0109
0110
0111 for (std::size_t i = 0; i < n - 1; i++, a -= diff)
0112 {
0113 Point p;
0114 set<0>(p, get<0>(vertex) + buffer_distance * cos(a));
0115 set<1>(p, get<1>(vertex) + buffer_distance * sin(a));
0116 range_out.push_back(p);
0117 }
0118 }
0119
0120 public :
0121
0122
0123 #ifndef DOXYGEN_SHOULD_SKIP_THIS
0124
0125 template <typename Point, typename DistanceType, typename RangeOut>
0126 inline bool apply(Point const& ip, Point const& vertex,
0127 Point const& perp1, Point const& perp2,
0128 DistanceType const& buffer_distance,
0129 RangeOut& range_out) const
0130 {
0131 typedef typename coordinate_type<Point>::type coordinate_type;
0132 typedef typename boost::range_value<RangeOut>::type output_point_type;
0133
0134 typedef typename geometry::select_most_precise
0135 <
0136 typename geometry::select_most_precise
0137 <
0138 coordinate_type,
0139 typename geometry::coordinate_type<output_point_type>::type
0140 >::type,
0141 double
0142 >::type promoted_type;
0143
0144 geometry::equal_to<Point> equals;
0145 if (equals(perp1, perp2))
0146 {
0147 boost::ignore_unused(ip);
0148 #ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
0149 std::cout << "Corner for equal points " << geometry::wkt(ip) << " " << geometry::wkt(perp1) << std::endl;
0150 #endif
0151 return false;
0152 }
0153
0154 range_out.push_back(perp1);
0155 generate_points<promoted_type>(vertex, perp1, perp2, geometry::math::abs(buffer_distance), range_out);
0156 range_out.push_back(perp2);
0157 return true;
0158 }
0159
0160 template <typename NumericType>
0161 static inline NumericType max_distance(NumericType const& distance)
0162 {
0163 return distance;
0164 }
0165
0166 #endif
0167
0168 private :
0169 std::size_t m_points_per_circle;
0170 };
0171
0172
0173 }}
0174
0175 }}
0176
0177 #endif