File: circle.cpp

package info (click to toggle)
boost1.88 1.88.0-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 576,932 kB
  • sloc: cpp: 4,149,234; xml: 136,789; ansic: 35,092; python: 33,910; asm: 5,698; sh: 4,604; ada: 1,681; makefile: 1,633; pascal: 1,139; perl: 1,124; sql: 640; yacc: 478; ruby: 271; java: 77; lisp: 24; csh: 6
file content (79 lines) | stat: -rw-r--r-- 2,816 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//
// Copyright 2020 Olzhas Zhumabek <anonymous.from.applecity@gmail.com>
//
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//

#include <boost/gil/point.hpp>
#include <boost/gil/extension/rasterization/circle.hpp>

#include <boost/core/lightweight_test.hpp>

#include <cmath>
#include <cstdint>
#include <vector>

namespace gil = boost::gil;

template <typename Rasterizer>
void test_rasterizer_follows_equation(Rasterizer rasterizer)
{
    std::ptrdiff_t const radius = rasterizer.radius;
    std::vector<gil::point_t> circle_points(rasterizer.point_count());
    std::ptrdiff_t const r_squared = radius * radius;
    rasterizer(circle_points.begin());
    std::vector<gil::point_t> first_octant(rasterizer.point_count() / 8);

    for (std::size_t i = 0, octant_index = 0; i < circle_points.size(); i += 8, ++octant_index)
    {
        first_octant[octant_index] = circle_points[i];
    }

    for (auto const& point : first_octant)
    {
        double const y_exact = std::sqrt(r_squared - point.x * point.x);
        std::ptrdiff_t lower_result = static_cast<std::ptrdiff_t>(std::floor(y_exact));
        std::ptrdiff_t upper_result = static_cast<std::ptrdiff_t>(std::ceil(y_exact));
        BOOST_TEST(point.y >= lower_result && point.y <= upper_result);
    }
}

template <typename Rasterizer>
void test_connectivity(Rasterizer rasterizer)
{
    std::vector<gil::point_t> circle_points(rasterizer.point_count());
    rasterizer(circle_points.begin());
    for (std::size_t i = 0; i < 8; ++i)
    {
        std::vector<gil::point_t> octant(circle_points.size() / 8);
        for (std::size_t octant_index = i, index = 0; octant_index < circle_points.size();
             octant_index += 8, ++index)
        {
            octant[index] = circle_points[octant_index];
        }

        for (std::size_t index = 1; index < octant.size(); ++index)
        {
            const auto diff_x = std::abs(octant[index].x - octant[index - 1].x);
            const auto diff_y = std::abs(octant[index].y - octant[index - 1].y);
            BOOST_TEST_LE(diff_x, 1);
            BOOST_TEST_LE(diff_y, 1);
        }
    }
}

int main()
{
    for (std::ptrdiff_t radius = 5; radius <= 512; ++radius)
    {
        test_rasterizer_follows_equation(gil::midpoint_circle_rasterizer{{0, 0}, radius});
        // TODO: find out a new testing procedure for trigonometric rasterizer
        // test_equation_following(radius, gil::trigonometric_circle_rasterizer{});
        test_connectivity(gil::midpoint_circle_rasterizer{{radius, radius}, radius});
        test_connectivity(gil::trigonometric_circle_rasterizer{{radius, radius}, radius});
    }

    return boost::report_errors();
}