GCC Code Coverage Report


Directory: ./
File: tasks/dorogin_v_bin_img_conv_hull/tbb/src/ops_tbb.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 68 72 94.4%
Functions: 9 11 81.8%
Branches: 56 70 80.0%

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