File indexing completed on 2025-12-16 09:51:50
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_GIL_EXTENSION_RASTERIZATION_CIRCLE_HPP
0009 #define BOOST_GIL_EXTENSION_RASTERIZATION_CIRCLE_HPP
0010
0011 #include <boost/gil/detail/math.hpp>
0012 #include <boost/gil/extension/rasterization/apply_rasterizer.hpp>
0013 #include <boost/gil/point.hpp>
0014
0015 #include <cmath>
0016 #include <cstddef>
0017 #include <vector>
0018
0019 namespace boost { namespace gil {
0020
0021 struct circle_rasterizer_t{};
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 struct trigonometric_circle_rasterizer
0038 {
0039 using type = circle_rasterizer_t;
0040
0041
0042
0043
0044
0045 trigonometric_circle_rasterizer(point_t center_point, std::ptrdiff_t circle_radius)
0046 : center(center_point), radius(circle_radius)
0047 {}
0048
0049
0050
0051
0052
0053 double minimum_angle_step() const noexcept
0054 {
0055 const auto diameter = radius * 2 - 1;
0056 return std::atan2(1.0, diameter);
0057 }
0058
0059
0060 std::ptrdiff_t point_count() const noexcept
0061 {
0062 return 8 * static_cast<std::ptrdiff_t>(
0063 std::round(detail::pi / 4 / minimum_angle_step()) + 1);
0064 }
0065
0066
0067 template <typename OutputIterator>
0068 void operator()(OutputIterator d_first) const
0069 {
0070 const double minimum_angle_step = std::atan2(1.0, radius);
0071 auto translate_mirror_points = [this, &d_first](point_t p) {
0072 *d_first++ = point_t{center.x + p.x, center.y + p.y};
0073 *d_first++ = point_t{center.x + p.x, center.y - p.y};
0074 *d_first++ = point_t{center.x - p.x, center.y + p.y};
0075 *d_first++ = point_t{center.x - p.x, center.y - p.y};
0076 *d_first++ = point_t{center.x + p.y, center.y + p.x};
0077 *d_first++ = point_t{center.x + p.y, center.y - p.x};
0078 *d_first++ = point_t{center.x - p.y, center.y + p.x};
0079 *d_first++ = point_t{center.x - p.y, center.y - p.x};
0080 };
0081 const std::ptrdiff_t iteration_count = point_count() / 8;
0082 double angle = 0;
0083
0084 for (std::ptrdiff_t i = 0; i < iteration_count; ++i, angle += minimum_angle_step)
0085 {
0086 std::ptrdiff_t x = static_cast<std::ptrdiff_t>(std::round(radius * std::cos(angle)));
0087 std::ptrdiff_t y = static_cast<std::ptrdiff_t>(std::round(radius * std::sin(angle)));
0088 translate_mirror_points({x, y});
0089 }
0090 }
0091
0092 point_t center;
0093 std::ptrdiff_t radius;
0094 };
0095
0096
0097
0098
0099
0100
0101
0102 struct midpoint_circle_rasterizer
0103 {
0104 using type = circle_rasterizer_t;
0105
0106
0107
0108
0109
0110 midpoint_circle_rasterizer(point_t center_point, std::ptrdiff_t circle_radius)
0111 : center(center_point), radius(circle_radius)
0112 {}
0113
0114
0115 std::ptrdiff_t point_count() const noexcept
0116 {
0117
0118
0119
0120 return 8 * static_cast<std::ptrdiff_t>(
0121 std::round(radius * std::cos(boost::gil::detail::pi / 4)) + 1);
0122 }
0123
0124
0125 template <typename OutputIterator>
0126 void operator()(OutputIterator d_first) const
0127 {
0128 auto translate_mirror_points = [this, &d_first](point_t p) {
0129 *d_first++ = point_t{center.x + p.x, center.y + p.y};
0130 *d_first++ = point_t{center.x + p.x, center.y - p.y};
0131 *d_first++ = point_t{center.x - p.x, center.y + p.y};
0132 *d_first++ = point_t{center.x - p.x, center.y - p.y};
0133 *d_first++ = point_t{center.x + p.y, center.y + p.x};
0134 *d_first++ = point_t{center.x + p.y, center.y - p.x};
0135 *d_first++ = point_t{center.x - p.y, center.y + p.x};
0136 *d_first++ = point_t{center.x - p.y, center.y - p.x};
0137 };
0138 std::ptrdiff_t iteration_distance = point_count() / 8;
0139 std::ptrdiff_t y_current = radius;
0140 std::ptrdiff_t r_squared = radius * radius;
0141 translate_mirror_points({0, y_current});
0142 for (std::ptrdiff_t x = 1; x < iteration_distance; ++x)
0143 {
0144 std::ptrdiff_t midpoint = x * x + y_current * y_current - y_current - r_squared;
0145 if (midpoint > 0)
0146 {
0147 --y_current;
0148 }
0149 translate_mirror_points({x, y_current});
0150 }
0151 }
0152
0153 point_t center;
0154 std::ptrdiff_t radius;
0155 };
0156
0157 namespace detail {
0158
0159 template <typename View, typename Rasterizer, typename Pixel>
0160 struct apply_rasterizer_op<View, Rasterizer, Pixel, circle_rasterizer_t>
0161 {
0162 void operator()(
0163 View const& view, Rasterizer const& rasterizer, Pixel const& pixel)
0164 {
0165 std::vector<point_t> trajectory(rasterizer.point_count());
0166 rasterizer(std::begin(trajectory));
0167
0168 for (auto const& point : trajectory)
0169 {
0170 view(point) = pixel;
0171 }
0172 }
0173 };
0174
0175 }
0176
0177 }}
0178
0179 #endif