GCC Code Coverage Report


Directory: ./
File: tasks/dorogin_v_bin_img_conv_hull/omp/src/ops_omp.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 63 67 94.0%
Functions: 8 10 80.0%
Branches: 52 64 81.2%

Line Branch Exec Source
1 #include "dorogin_v_bin_img_conv_hull/omp/include/ops_omp.hpp"
2
3 #include <omp.h>
4
5 #include <algorithm>
6 #include <array>
7 #include <cstddef>
8 #include <cstdint>
9 #include <functional>
10 #include <ranges>
11 #include <stack>
12 #include <utility>
13 #include <vector>
14
15 #include "dorogin_v_bin_img_conv_hull/common/include/common.hpp"
16 #include "util/include/util.hpp"
17
18 namespace dorogin_v_bin_img_conv_hull {
19
20 namespace {
21
22 constexpr std::uint8_t kThreshold = 128;
23
24 inline bool IsInside(int col, int row, int width, int height) {
25 2928 return col >= 0 && row >= 0 && col < width && row < height;
26 }
27
28 std::int64_t Cross(const Point &a, const Point &b, const Point &c) {
29 1208 const std::int64_t x1 = static_cast<std::int64_t>(b.x) - static_cast<std::int64_t>(a.x);
30 1208 const std::int64_t y1 = static_cast<std::int64_t>(b.y) - static_cast<std::int64_t>(a.y);
31 1208 const std::int64_t x2 = static_cast<std::int64_t>(c.x) - static_cast<std::int64_t>(a.x);
32 1208 const std::int64_t y2 = static_cast<std::int64_t>(c.y) - static_cast<std::int64_t>(a.y);
33
2/2
✓ Branch 0 taken 280 times.
✓ Branch 1 taken 324 times.
604 return (x1 * y2) - (y1 * x2);
34 }
35
36 } // namespace
37
38
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 DoroginVBinImgConvHullOMP::DoroginVBinImgConvHullOMP(const InType &in) : w_(in) {
39 SetTypeOfTask(GetStaticTypeOfTask());
40
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 GetInput() = in;
41 20 }
42
43 20 bool DoroginVBinImgConvHullOMP::ValidationImpl() {
44 const auto &in = GetInput();
45
2/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 if (in.width <= 0 || in.height <= 0) {
46 return false;
47 }
48 20 return in.pixels.size() == static_cast<std::size_t>(in.width) * static_cast<std::size_t>(in.height);
49 }
50
51 20 bool DoroginVBinImgConvHullOMP::PreProcessingImpl() {
52 20 w_ = GetInput();
53 ThresholdImage();
54 20 return true;
55 }
56
57 20 bool DoroginVBinImgConvHullOMP::RunImpl() {
58 20 FindComponents();
59
60 w_.convex_hulls.clear();
61 20 w_.convex_hulls.resize(w_.components.size());
62
63 20 auto &components = w_.components;
64 auto &convex_hulls = w_.convex_hulls;
65 20 #pragma omp parallel for default(none) shared(components, convex_hulls) num_threads(ppc::util::GetNumThreads())
66 for (std::size_t i = 0; i < components.size(); ++i) {
67 const auto &comp = components[i];
68 if (comp.empty()) {
69 continue;
70 }
71 if (comp.size() <= 2) {
72 convex_hulls[i] = comp;
73 } else {
74 convex_hulls[i] = BuildHull(comp);
75 }
76 }
77
78 20 GetOutput() = w_;
79 20 return true;
80 }
81
82 20 bool DoroginVBinImgConvHullOMP::PostProcessingImpl() {
83 20 return true;
84 }
85
86 std::size_t DoroginVBinImgConvHullOMP::Index(int col, int row, int width) {
87
4/4
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 680 times.
✓ Branch 2 taken 784 times.
✓ Branch 3 taken 656 times.
2488 return (static_cast<std::size_t>(row) * static_cast<std::size_t>(width)) + static_cast<std::size_t>(col);
88 }
89
90 void DoroginVBinImgConvHullOMP::ThresholdImage() {
91 std::ranges::transform(w_.pixels, w_.pixels.begin(), [](std::uint8_t p) {
92
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 680 times.
✓ Branch 3 taken 368 times.
1048 return p > kThreshold ? static_cast<std::uint8_t>(255) : static_cast<std::uint8_t>(0);
93 });
94 }
95
96 24 void DoroginVBinImgConvHullOMP::ExploreComponent(int start_col, int start_row, int width, int height,
97 std::vector<bool> &visited, std::vector<Point> &component) {
98 std::stack<Point> stack;
99 stack.emplace(start_col, start_row);
100
101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 visited[Index(start_col, start_row, width)] = true;
102
103 24 const std::array<int, 4> dx{1, -1, 0, 0};
104 24 const std::array<int, 4> dy{0, 0, 1, -1};
105
106
2/2
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 24 times.
392 while (!stack.empty()) {
107
1/2
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
368 Point p = stack.top();
108 stack.pop();
109
110 component.push_back(p);
111
112
2/2
✓ Branch 0 taken 1472 times.
✓ Branch 1 taken 368 times.
1840 for (std::size_t dir = 0; dir < dx.size(); ++dir) {
113 1472 const int nx = p.x + dx.at(dir);
114
2/2
✓ Branch 0 taken 1456 times.
✓ Branch 1 taken 16 times.
1472 const int ny = p.y + dy.at(dir);
115
116
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1440 times.
1456 if (!IsInside(nx, ny, width, height)) {
117 1128 continue;
118 }
119
120 const std::size_t idx = Index(nx, ny, width);
121
2/2
✓ Branch 0 taken 784 times.
✓ Branch 1 taken 656 times.
1440 if (visited[idx]) {
122 784 continue;
123 }
124
2/2
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 344 times.
656 if (w_.pixels[idx] == 0) {
125 312 continue;
126 }
127
128 visited[idx] = true;
129 stack.emplace(nx, ny);
130 }
131 }
132 24 }
133
134 20 void DoroginVBinImgConvHullOMP::FindComponents() {
135 20 const int width = w_.width;
136 20 const int height = w_.height;
137
138
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 std::vector<bool> visited(static_cast<std::size_t>(width) * static_cast<std::size_t>(height), false);
139 w_.components.clear();
140
141
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 20 times.
148 for (int row = 0; row < height; ++row) {
142
2/2
✓ Branch 0 taken 1048 times.
✓ Branch 1 taken 128 times.
1176 for (int col = 0; col < width; ++col) {
143 const std::size_t idx = Index(col, row, width);
144
145
4/4
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 680 times.
✓ Branch 2 taken 344 times.
✓ Branch 3 taken 24 times.
1048 if (w_.pixels[idx] == 0 || visited[idx]) {
146 1024 continue;
147 }
148
149 24 std::vector<Point> comp;
150
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 ExploreComponent(col, row, width, height, visited, comp);
151
152
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 w_.components.push_back(std::move(comp));
153 }
154 }
155 20 }
156
157 12 std::vector<Point> DoroginVBinImgConvHullOMP::BuildHull(const std::vector<Point> &points) {
158 12 std::vector<Point> pts = points;
159
160 std::ranges::sort(pts, std::less<>{});
161 const auto uniq = std::ranges::unique(pts);
162 pts.erase(uniq.begin(), uniq.end());
163
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (pts.size() <= 2) {
165 return pts;
166 }
167
168 12 std::vector<Point> hull;
169
170
2/2
✓ Branch 0 taken 356 times.
✓ Branch 1 taken 12 times.
368 for (const auto &p : pts) {
171
4/4
✓ Branch 0 taken 604 times.
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 324 times.
✓ Branch 3 taken 280 times.
680 while (hull.size() >= 2 && Cross(hull[hull.size() - 2], hull.back(), p) <= 0) {
172 hull.pop_back();
173 }
174 hull.push_back(p);
175 }
176
177 const std::size_t lsize = hull.size();
178
2/2
✓ Branch 0 taken 344 times.
✓ Branch 1 taken 12 times.
356 for (int i = static_cast<int>(pts.size()) - 2; i >= 0; --i) {
179
4/4
✓ Branch 0 taken 604 times.
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 280 times.
✓ Branch 3 taken 324 times.
668 while (hull.size() > lsize && Cross(hull[hull.size() - 2], hull.back(), pts[static_cast<std::size_t>(i)]) <= 0) {
180 hull.pop_back();
181 }
182
2/2
✓ Branch 0 taken 332 times.
✓ Branch 1 taken 12 times.
344 hull.push_back(pts[static_cast<std::size_t>(i)]);
183 }
184
185 hull.pop_back();
186 return hull;
187 }
188
189 } // namespace dorogin_v_bin_img_conv_hull
190