File indexing completed on 2025-01-18 09:36:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_ROUND_HPP
0015 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_END_ROUND_HPP
0016
0017 #include <boost/core/ignore_unused.hpp>
0018
0019 #include <boost/geometry/arithmetic/arithmetic.hpp>
0020 #include <boost/geometry/core/cs.hpp>
0021 #include <boost/geometry/core/access.hpp>
0022 #include <boost/geometry/strategies/tags.hpp>
0023 #include <boost/geometry/util/math.hpp>
0024 #include <boost/geometry/util/select_most_precise.hpp>
0025
0026 #include <boost/geometry/strategies/buffer.hpp>
0027
0028
0029 namespace boost { namespace geometry
0030 {
0031
0032
0033 namespace strategy { namespace buffer
0034 {
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 class end_round
0056 {
0057 private :
0058 std::size_t m_points_per_circle;
0059
0060 template
0061 <
0062 typename Point,
0063 typename PromotedType,
0064 typename DistanceType,
0065 typename RangeOut
0066 >
0067 inline void generate_points(Point const& point,
0068 PromotedType alpha,
0069 DistanceType const& buffer_distance,
0070 RangeOut& range_out) const
0071 {
0072 PromotedType const two_pi = geometry::math::two_pi<PromotedType>();
0073
0074 std::size_t point_buffer_count = m_points_per_circle;
0075
0076 PromotedType const diff = two_pi / PromotedType(point_buffer_count);
0077
0078
0079 point_buffer_count /= 2;
0080 point_buffer_count++;
0081
0082 for (std::size_t i = 0; i < point_buffer_count; i++, alpha -= diff)
0083 {
0084 typename boost::range_value<RangeOut>::type p;
0085 geometry::set<0>(p, geometry::get<0>(point) + buffer_distance * cos(alpha));
0086 geometry::set<1>(p, geometry::get<1>(point) + buffer_distance * sin(alpha));
0087 range_out.push_back(p);
0088 }
0089 }
0090
0091 template <typename T, typename P1, typename P2>
0092 static inline T calculate_angle(P1 const& from_point, P2 const& to_point)
0093 {
0094 typedef P1 vector_type;
0095 vector_type v = from_point;
0096 geometry::subtract_point(v, to_point);
0097 return atan2(geometry::get<1>(v), geometry::get<0>(v));
0098 }
0099
0100 public :
0101
0102
0103
0104 explicit inline end_round(std::size_t points_per_circle = default_points_per_circle)
0105 : m_points_per_circle(get_point_count_for_end(points_per_circle))
0106 {}
0107
0108 #ifndef DOXYGEN_SHOULD_SKIP_THIS
0109
0110
0111 template <typename Point, typename DistanceStrategy, typename RangeOut>
0112 inline void apply(Point const& penultimate_point,
0113 Point const& perp_left_point,
0114 Point const& ultimate_point,
0115 Point const& perp_right_point,
0116 buffer_side_selector side,
0117 DistanceStrategy const& distance,
0118 RangeOut& range_out) const
0119 {
0120 boost::ignore_unused(perp_left_point);
0121 typedef typename coordinate_type<Point>::type coordinate_type;
0122
0123 typedef typename geometry::select_most_precise
0124 <
0125 coordinate_type,
0126 double
0127 >::type promoted_type;
0128
0129 promoted_type const dist_left = distance.apply(penultimate_point, ultimate_point, buffer_side_left);
0130 promoted_type const dist_right = distance.apply(penultimate_point, ultimate_point, buffer_side_right);
0131 promoted_type const alpha
0132 = calculate_angle<promoted_type>(penultimate_point, ultimate_point)
0133 - geometry::math::half_pi<promoted_type>();
0134
0135 if (geometry::math::equals(dist_left, dist_right))
0136 {
0137 generate_points(ultimate_point, alpha, dist_left, range_out);
0138 }
0139 else
0140 {
0141 static promoted_type const two = 2.0;
0142 promoted_type const dist_average = (dist_left + dist_right) / two;
0143 promoted_type const dist_half
0144 = (side == buffer_side_right
0145 ? (dist_right - dist_left)
0146 : (dist_left - dist_right)) / two;
0147
0148 Point shifted_point;
0149 geometry::set<0>(shifted_point, geometry::get<0>(ultimate_point) + dist_half * cos(alpha));
0150 geometry::set<1>(shifted_point, geometry::get<1>(ultimate_point) + dist_half * sin(alpha));
0151 generate_points(shifted_point, alpha, dist_average, range_out);
0152 }
0153
0154 if (m_points_per_circle % 2 == 1)
0155 {
0156
0157
0158 range_out.push_back(perp_right_point);
0159 }
0160 }
0161
0162 template <typename NumericType>
0163 static inline NumericType max_distance(NumericType const& distance)
0164 {
0165 return distance;
0166 }
0167
0168
0169 static inline piece_type get_piece_type()
0170 {
0171 return buffered_round_end;
0172 }
0173 #endif
0174 };
0175
0176
0177 }}
0178
0179 }}
0180
0181 #endif