File indexing completed on 2025-12-16 09:51:50
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_GIL_EXTENSION_RASTERIZATION_ELLIPSE_HPP
0009 #define BOOST_GIL_EXTENSION_RASTERIZATION_ELLIPSE_HPP
0010
0011 #include <boost/gil/concepts/pixel.hpp>
0012 #include <boost/gil/extension/rasterization/apply_rasterizer.hpp>
0013 #include <boost/gil/point.hpp>
0014
0015 #include <array>
0016 #include <stdexcept>
0017 #include <vector>
0018
0019 namespace boost { namespace gil {
0020
0021 struct ellipse_rasterizer_t{};
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 struct midpoint_ellipse_rasterizer
0032 {
0033 using type = ellipse_rasterizer_t;
0034
0035
0036
0037
0038
0039
0040 midpoint_ellipse_rasterizer(point<unsigned int> center_point,
0041 point<unsigned int> semi_axes_values)
0042 : center(center_point)
0043 , semi_axes(semi_axes_values)
0044 {}
0045
0046
0047
0048 auto obtain_trajectory() const
0049 -> std::vector<point_t>
0050 {
0051
0052
0053
0054
0055
0056 std::vector<point_t> trajectory_points;
0057 std::ptrdiff_t x = semi_axes[0], y = 0;
0058
0059
0060
0061
0062 long long int const t1 = semi_axes[0] * semi_axes[0];
0063 long long int const t4 = semi_axes[1] * semi_axes[1];
0064 long long int t2, t3, t5, t6, t8, t9;
0065 t2 = 2 * t1, t3 = 2 * t2;
0066 t5 = 2 * t4, t6 = 2 * t5;
0067 long long int const t7 = semi_axes[0] * t5;
0068 t8 = 2 * t7, t9 = 0;
0069
0070
0071
0072 long long int d1, d2;
0073 d1 = t2 - t7 + t4 / 2, d2 = t1 / 2 - t8 + t5;
0074
0075 while (d2 < 0)
0076 {
0077 trajectory_points.push_back({x, y});
0078 y += 1;
0079 t9 += t3;
0080 if (d1 < 0)
0081 {
0082 d1 += t9 + t2;
0083 d2 += t9;
0084 }
0085 else
0086 {
0087 x -= 1;
0088 t8 -= t6;
0089 d1 += t9 + t2 - t8;
0090 d2 += t5 + t9 - t8;
0091 }
0092 }
0093 while (x >= 0)
0094 {
0095 trajectory_points.push_back({x, y});
0096 x -= 1;
0097 t8 -= t6;
0098 if (d2 < 0)
0099 {
0100 y += 1;
0101 t9 += t3;
0102 d2 += t5 + t9 - t8;
0103 }
0104 else
0105 {
0106 d2 += t5 - t8;
0107 }
0108 }
0109 return trajectory_points;
0110 }
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121 template<typename View, typename Pixel>
0122 void draw_curve(View& view, Pixel const& pixel,
0123 std::vector<point_t> const& trajectory_points) const
0124 {
0125 using pixel_t = typename View::value_type;
0126 if (!pixels_are_compatible<pixel_t, Pixel>())
0127 {
0128 throw std::runtime_error("Pixel type of the given image is not compatible to the "
0129 "type of the provided pixel.");
0130 }
0131
0132
0133 point<unsigned int> center2(center);
0134 --center2[0], --center2[1];
0135 for (point_t pnt : trajectory_points)
0136 {
0137 std::array<std::ptrdiff_t, 4> co_ords = {center2[0] + pnt[0],
0138 center2[0] - pnt[0], center2[1] + pnt[1], center2[1] - pnt[1]
0139 };
0140 bool validity[4]{};
0141 if (co_ords[0] < view.width())
0142 {
0143 validity[0] = true;
0144 }
0145 if (co_ords[1] >= 0 && co_ords[1] < view.width())
0146 {
0147 validity[1] = true;
0148 }
0149 if (co_ords[2] < view.height())
0150 {
0151 validity[2] = true;
0152 }
0153 if (co_ords[3] >= 0 && co_ords[3] < view.height())
0154 {
0155 validity[3] = true;
0156 }
0157
0158 if (validity[0] && validity[2])
0159 {
0160 view(co_ords[0], co_ords[2]) = pixel;
0161 }
0162 if (validity[1] && validity[2])
0163 {
0164 view(co_ords[1], co_ords[2]) = pixel;
0165 }
0166 if (validity[1] && validity[3])
0167 {
0168 view(co_ords[1], co_ords[3]) = pixel;
0169 }
0170 if (validity[0] && validity[3])
0171 {
0172 view(co_ords[0], co_ords[3]) = pixel;
0173 }
0174 }
0175 }
0176
0177
0178
0179
0180
0181
0182
0183 template<typename View, typename Pixel>
0184 void operator()(View& view, Pixel const& pixel) const
0185 {
0186 draw_curve(view, pixel, obtain_trajectory());
0187 }
0188
0189 point<unsigned int> center;
0190 point<unsigned int> semi_axes;
0191 };
0192
0193 namespace detail {
0194
0195 template <typename View, typename Rasterizer, typename Pixel>
0196 struct apply_rasterizer_op<View, Rasterizer, Pixel, ellipse_rasterizer_t>
0197 {
0198 void operator()(
0199 View const& view, Rasterizer const& rasterizer, Pixel const& pixel)
0200 {
0201 rasterizer(view, pixel);
0202 }
0203 };
0204
0205 }
0206
0207 }}
0208
0209 #endif