contrek 1.2.8 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.rubocop.yml +11 -0
- data/CHANGELOG.md +7 -1
- data/Gemfile +2 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/Rakefile +2 -0
- data/contrek.gemspec +2 -0
- data/ext/cpp_polygon_finder/PolygonFinder/CMakeLists.txt +2 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +118 -19
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.h +1 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.cpp +5 -7
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.h +4 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.cpp +14 -15
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.h +2 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Polygon.h +2 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.cpp +13 -13
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +79 -354
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.cpp +6 -6
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.h +3 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.cpp +8 -8
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/EndPoint.h +4 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.h +3 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/InnerPolyline.cpp +6 -6
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/InnerPolyline.h +3 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Merger.cpp +4 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.cpp +29 -9
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.h +3 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.cpp +45 -30
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +18 -19
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +6 -5
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.cpp +2 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.h +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Queueable.h +4 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.cpp +7 -7
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.h +2 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.cpp +8 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.h +4 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ShapePool.cpp +19 -5
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ShapePool.h +6 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.cpp +117 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.h +41 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.cpp +9 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.h +1 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.cpp +4 -13
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.h +1 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/LinearReducer.cpp +8 -8
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/LinearReducer.h +2 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/Reducer.cpp +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/Reducer.h +2 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/UniqReducer.cpp +3 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/UniqReducer.h +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/VisvalingamReducer.cpp +3 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/VisvalingamReducer.h +10 -10
- data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +66 -16
- data/ext/cpp_polygon_finder/extconf.rb +2 -0
- data/lib/contrek/bitmaps/bitmap.rb +2 -0
- data/lib/contrek/bitmaps/chunky_bitmap.rb +13 -0
- data/lib/contrek/bitmaps/painting.rb +2 -0
- data/lib/contrek/bitmaps/png_bitmap.rb +2 -0
- data/lib/contrek/bitmaps/raw_bitmap.rb +2 -0
- data/lib/contrek/bitmaps/rgb_color.rb +2 -0
- data/lib/contrek/bitmaps/rgb_cpp_color.rb +2 -0
- data/lib/contrek/bitmaps/sample_generator.rb +2 -0
- data/lib/contrek/cpp/cpp_concurrent_finder.rb +2 -0
- data/lib/contrek/cpp/cpp_concurrent_horizontal_merger.rb +2 -0
- data/lib/contrek/cpp/cpp_concurrent_merger.rb +2 -0
- data/lib/contrek/cpp/cpp_concurrent_streaming_merger.rb +11 -0
- data/lib/contrek/cpp/cpp_concurrent_vertical_merger.rb +2 -0
- data/lib/contrek/cpp/cpp_result.rb +2 -0
- data/lib/contrek/cpp/cpp_tempfile.rb +28 -0
- data/lib/contrek/finder/bounds.rb +2 -0
- data/lib/contrek/finder/concurrent/clipped_polygon_finder.rb +2 -0
- data/lib/contrek/finder/concurrent/cluster.rb +3 -1
- data/lib/contrek/finder/concurrent/cursor.rb +2 -0
- data/lib/contrek/finder/concurrent/end_point.rb +2 -0
- data/lib/contrek/finder/concurrent/fake_cluster.rb +2 -0
- data/lib/contrek/finder/concurrent/finder.rb +6 -0
- data/lib/contrek/finder/concurrent/horizontal_merger.rb +2 -0
- data/lib/contrek/finder/concurrent/hub.rb +2 -0
- data/lib/contrek/finder/concurrent/inner_polyline.rb +2 -0
- data/lib/contrek/finder/concurrent/listable.rb +2 -0
- data/lib/contrek/finder/concurrent/merger.rb +4 -0
- data/lib/contrek/finder/concurrent/part.rb +13 -0
- data/lib/contrek/finder/concurrent/partitionable.rb +33 -17
- data/lib/contrek/finder/concurrent/polyline.rb +2 -0
- data/lib/contrek/finder/concurrent/poolable.rb +2 -0
- data/lib/contrek/finder/concurrent/position.rb +2 -0
- data/lib/contrek/finder/concurrent/queueable.rb +2 -0
- data/lib/contrek/finder/concurrent/sequence.rb +2 -0
- data/lib/contrek/finder/concurrent/shape.rb +2 -0
- data/lib/contrek/finder/concurrent/streaming_merger.rb +89 -0
- data/lib/contrek/finder/concurrent/tile.rb +2 -0
- data/lib/contrek/finder/concurrent/vertical_merger.rb +8 -2
- data/lib/contrek/finder/list.rb +2 -0
- data/lib/contrek/finder/list_entry.rb +2 -0
- data/lib/contrek/finder/listable.rb +2 -0
- data/lib/contrek/finder/lists.rb +2 -0
- data/lib/contrek/finder/node.rb +2 -0
- data/lib/contrek/finder/node_cluster.rb +3 -1
- data/lib/contrek/finder/polygon_finder.rb +4 -1
- data/lib/contrek/finder/result.rb +2 -0
- data/lib/contrek/map/mercator_projection.rb +2 -0
- data/lib/contrek/matchers/matcher.rb +2 -0
- data/lib/contrek/matchers/matcher_hsb.rb +2 -0
- data/lib/contrek/matchers/value_not_matcher.rb +2 -0
- data/lib/contrek/reducers/linear_reducer.rb +2 -0
- data/lib/contrek/reducers/reducer.rb +2 -0
- data/lib/contrek/reducers/uniq_reducer.rb +2 -0
- data/lib/contrek/reducers/visvalingam_reducer.rb +2 -0
- data/lib/contrek/shared/result.rb +2 -0
- data/lib/contrek/version.rb +3 -1
- data/lib/contrek.rb +5 -0
- metadata +11 -5
|
@@ -61,12 +61,12 @@ struct pf_Options {
|
|
|
61
61
|
struct ProcessResult {
|
|
62
62
|
int groups;
|
|
63
63
|
int width, height;
|
|
64
|
+
int versus;
|
|
64
65
|
bool has_bounds = false;
|
|
65
66
|
std::map<std::string, double> benchmarks;
|
|
66
67
|
std::list<Polygon> polygons;
|
|
67
68
|
std::string named_sequence;
|
|
68
69
|
std::vector<std::pair<int, int>> treemap;
|
|
69
|
-
std::vector<Point> cloned_points_storage;
|
|
70
70
|
|
|
71
71
|
void draw_on_bitmap(RawBitmap& canvas) const;
|
|
72
72
|
|
|
@@ -74,12 +74,12 @@ struct ProcessResult {
|
|
|
74
74
|
int counter = 0;
|
|
75
75
|
for (const auto& polygon : polygons) {
|
|
76
76
|
std::cout << counter << " - " << "outer" << "\n";
|
|
77
|
-
for (const Point
|
|
77
|
+
for (const Point& p : polygon.outer) std::cout << p.toString();
|
|
78
78
|
bool first = true;
|
|
79
79
|
for (const auto& seq : polygon.inner) {
|
|
80
80
|
if (!first) std::cout << "\n";
|
|
81
81
|
first = false;
|
|
82
|
-
for (const Point
|
|
82
|
+
for (const Point& p : seq) std::cout << p.toString();
|
|
83
83
|
}
|
|
84
84
|
std::cout << "\n" << polygon.bounds.to_string() <<"\n";
|
|
85
85
|
counter++;
|
|
@@ -95,61 +95,15 @@ struct ProcessResult {
|
|
|
95
95
|
|
|
96
96
|
void translate(int x) {
|
|
97
97
|
for (auto& polygon : polygons) {
|
|
98
|
-
for (Point
|
|
99
|
-
for (
|
|
100
|
-
for (Point
|
|
98
|
+
for (Point& p : polygon.outer) p.x += x;
|
|
99
|
+
for (auto& seq : polygon.inner) {
|
|
100
|
+
for (Point& p : seq) p.x += x;
|
|
101
101
|
}
|
|
102
102
|
polygon.bounds.min_x += x;
|
|
103
103
|
polygon.bounds.max_x += x;
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
ProcessResult* clone() const {
|
|
108
|
-
ProcessResult* new_res = new ProcessResult();
|
|
109
|
-
new_res->groups = this->groups;
|
|
110
|
-
new_res->width = this->width;
|
|
111
|
-
new_res->height = this->height;
|
|
112
|
-
new_res->benchmarks = this->benchmarks;
|
|
113
|
-
new_res->named_sequence = this->named_sequence;
|
|
114
|
-
new_res->treemap = this->treemap;
|
|
115
|
-
|
|
116
|
-
size_t estimated_points = 0;
|
|
117
|
-
for (const auto& poly : this->polygons) {
|
|
118
|
-
estimated_points += poly.outer.size();
|
|
119
|
-
for (const auto& seq : poly.inner) estimated_points += seq.size();
|
|
120
|
-
}
|
|
121
|
-
new_res->cloned_points_storage.reserve(estimated_points);
|
|
122
|
-
|
|
123
|
-
for (const auto& poly : this->polygons) {
|
|
124
|
-
Polygon new_poly;
|
|
125
|
-
new_poly.bounds = poly.bounds;
|
|
126
|
-
new_poly.outer.reserve(poly.outer.size());
|
|
127
|
-
// outer
|
|
128
|
-
for (const Point* p : poly.outer) {
|
|
129
|
-
if (p) {
|
|
130
|
-
new_res->cloned_points_storage.push_back(Point(p->x, p->y));
|
|
131
|
-
size_t idx = new_res->cloned_points_storage.size() - 1;
|
|
132
|
-
new_poly.outer.push_back(&new_res->cloned_points_storage[idx]);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
// inner
|
|
136
|
-
for (const auto& seq : poly.inner) {
|
|
137
|
-
std::vector<Point*> new_seq;
|
|
138
|
-
new_seq.reserve(seq.size());
|
|
139
|
-
for (const Point* p : seq) {
|
|
140
|
-
if (p) {
|
|
141
|
-
new_res->cloned_points_storage.push_back(Point(p->x, p->y));
|
|
142
|
-
size_t idx = new_res->cloned_points_storage.size() - 1;
|
|
143
|
-
new_seq.push_back(&new_res->cloned_points_storage[idx]);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
new_poly.inner.push_back(new_seq);
|
|
147
|
-
}
|
|
148
|
-
new_res->polygons.push_back(new_poly);
|
|
149
|
-
}
|
|
150
|
-
return new_res;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
107
|
void to_svg_stream(std::ostream& os) const {
|
|
154
108
|
os << "<svg xmlns=\"http://www.w3.org/2000/svg\" "
|
|
155
109
|
<< "width=\"" << width << "\" height=\"" << height << "\">\n";
|
|
@@ -158,11 +112,10 @@ struct ProcessResult {
|
|
|
158
112
|
if (!poly.outer.empty()) {
|
|
159
113
|
os << "<polygon points=\"";
|
|
160
114
|
bool first = true;
|
|
161
|
-
for (const Point
|
|
162
|
-
if (!p) continue;
|
|
115
|
+
for (const Point& p : poly.outer) {
|
|
163
116
|
if (!first) os << " ";
|
|
164
117
|
first = false;
|
|
165
|
-
os << p
|
|
118
|
+
os << p.x << "," << p.y;
|
|
166
119
|
}
|
|
167
120
|
os << "\" fill=\"none\" stroke=\"red\" stroke-width=\"1\"/>\n";
|
|
168
121
|
}
|
|
@@ -171,11 +124,10 @@ struct ProcessResult {
|
|
|
171
124
|
if (sequence.empty()) continue;
|
|
172
125
|
os << "<polygon points=\"";
|
|
173
126
|
bool first = true;
|
|
174
|
-
for (const Point
|
|
175
|
-
if (!p) continue;
|
|
127
|
+
for (const Point& p : sequence) {
|
|
176
128
|
if (!first) os << " ";
|
|
177
129
|
first = false;
|
|
178
|
-
os << p
|
|
130
|
+
os << p.x << "," << p.y;
|
|
179
131
|
}
|
|
180
132
|
os << "\" fill=\"none\" stroke=\"green\" stroke-width=\"1\"/>\n";
|
|
181
133
|
}
|
|
@@ -207,330 +159,103 @@ class PolygonFinder {
|
|
|
207
159
|
std::map<std::string, double> reports;
|
|
208
160
|
void scan();
|
|
209
161
|
CpuTimer cpu_timer;
|
|
210
|
-
|
|
162
|
+
|
|
211
163
|
template <typename M, typename F>
|
|
212
164
|
void run_loop(M* specific_matcher, F&& fetch_color, int offset) {
|
|
213
165
|
int img_h = this->source_bitmap->h();
|
|
214
166
|
int bpp = this->source_bitmap->get_bytes_per_pixel();
|
|
167
|
+
|
|
215
168
|
for (int y = 0; y < img_h; y++) {
|
|
216
169
|
const unsigned char* row_ptr = this->source_bitmap->get_row_ptr(y);
|
|
217
170
|
const unsigned char* p = row_ptr + (this->start_x * bpp);
|
|
171
|
+
|
|
218
172
|
int min_x = 0;
|
|
219
173
|
bool matching = false;
|
|
220
174
|
unsigned char last_red_value = 0;
|
|
221
|
-
for (int x = this->start_x; x < this->end_x; x++) {
|
|
222
|
-
unsigned int color = fetch_color(p);
|
|
223
|
-
unsigned char current_val = p[0];
|
|
224
|
-
p += bpp;
|
|
225
|
-
if (specific_matcher->match(color)) {
|
|
226
|
-
if (!matching) {
|
|
227
|
-
min_x = x;
|
|
228
|
-
last_red_value = current_val;
|
|
229
|
-
matching = true;
|
|
230
|
-
}
|
|
231
|
-
if (x == this->end_x - 1) {
|
|
232
|
-
this->node_cluster->add_node(min_x, x, y, last_red_value, offset);
|
|
233
|
-
matching = false;
|
|
234
|
-
}
|
|
235
|
-
} else if (matching) {
|
|
236
|
-
this->node_cluster->add_node(min_x, x - 1, y, last_red_value, offset);
|
|
237
|
-
matching = false;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}*/
|
|
242
|
-
|
|
243
|
-
template <typename M, typename F>
|
|
244
|
-
void run_loop(M* specific_matcher, F&& fetch_color, int offset) {
|
|
245
|
-
int img_h = this->source_bitmap->h();
|
|
246
|
-
int bpp = this->source_bitmap->get_bytes_per_pixel();
|
|
247
|
-
|
|
248
|
-
for (int y = 0; y < img_h; y++) {
|
|
249
|
-
const unsigned char* row_ptr = this->source_bitmap->get_row_ptr(y);
|
|
250
|
-
const unsigned char* p = row_ptr + (this->start_x * bpp);
|
|
251
|
-
|
|
252
|
-
int min_x = 0;
|
|
253
|
-
bool matching = false;
|
|
254
|
-
unsigned char last_red_value = 0;
|
|
255
|
-
|
|
256
|
-
int x = this->start_x;
|
|
257
|
-
|
|
258
|
-
if (bpp == 4) {
|
|
259
|
-
for (; x <= this->end_x - 4; x += 4) {
|
|
260
|
-
// 1. Unico accesso alla RAM per pixel: leggiamo i 4 byte completi
|
|
261
|
-
unsigned int c0 = fetch_color(p);
|
|
262
|
-
unsigned int c1 = fetch_color(p + 4);
|
|
263
|
-
unsigned int c2 = fetch_color(p + 8);
|
|
264
|
-
unsigned int c3 = fetch_color(p + 12);
|
|
265
|
-
|
|
266
|
-
// 2. Estrazione a costo zero dai registri della CPU (Operazione bitwise, NO RAM)
|
|
267
|
-
// Se fetch_color ritorna il mascheramento standard, il primo byte si prende con il cast o lo shift
|
|
268
|
-
unsigned char v0 = static_cast<unsigned char>(c0);
|
|
269
|
-
unsigned char v1 = static_cast<unsigned char>(c1);
|
|
270
|
-
unsigned char v2 = static_cast<unsigned char>(c2);
|
|
271
|
-
unsigned char v3 = static_cast<unsigned char>(c3);
|
|
272
175
|
|
|
273
|
-
|
|
176
|
+
int x = this->start_x;
|
|
274
177
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
178
|
+
if (bpp == 4) {
|
|
179
|
+
for (; x <= this->end_x - 4; x += 4) {
|
|
180
|
+
// read 4 pixels (16 bytes)
|
|
181
|
+
unsigned int c0 = fetch_color(p);
|
|
182
|
+
unsigned int c1 = fetch_color(p + 4);
|
|
183
|
+
unsigned int c2 = fetch_color(p + 8);
|
|
184
|
+
unsigned int c3 = fetch_color(p + 12);
|
|
279
185
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
matching = false;
|
|
286
|
-
}
|
|
186
|
+
// extracts value (used as debugging segment label)
|
|
187
|
+
unsigned char v0 = static_cast<unsigned char>(c0);
|
|
188
|
+
unsigned char v1 = static_cast<unsigned char>(c1);
|
|
189
|
+
unsigned char v2 = static_cast<unsigned char>(c2);
|
|
190
|
+
unsigned char v3 = static_cast<unsigned char>(c3);
|
|
287
191
|
|
|
288
|
-
|
|
289
|
-
if (!matching) { min_x = x + 1; last_red_value = v1; matching = true; }
|
|
290
|
-
} else if (matching) {
|
|
291
|
-
this->node_cluster->add_node(min_x, x, y, last_red_value, offset);
|
|
292
|
-
matching = false;
|
|
293
|
-
}
|
|
192
|
+
p += 16;
|
|
294
193
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
matching = false;
|
|
300
|
-
}
|
|
194
|
+
bool m0 = specific_matcher->match(c0);
|
|
195
|
+
bool m1 = specific_matcher->match(c1);
|
|
196
|
+
bool m2 = specific_matcher->match(c2);
|
|
197
|
+
bool m3 = specific_matcher->match(c3);
|
|
301
198
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
this->node_cluster->add_node(min_x, x + 2, y, last_red_value, offset);
|
|
306
|
-
matching = false;
|
|
307
|
-
}
|
|
199
|
+
if (m0) {
|
|
200
|
+
if (!matching) {
|
|
201
|
+
min_x = x; last_red_value = v0; matching = true;
|
|
308
202
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
unsigned int color = fetch_color(p);
|
|
314
|
-
// Applichiamo la stessa ottimizzazione anche qui
|
|
315
|
-
unsigned char current_val = static_cast<unsigned char>(color);
|
|
316
|
-
p += bpp;
|
|
317
|
-
|
|
318
|
-
if (specific_matcher->match(color)) {
|
|
319
|
-
if (!matching) {
|
|
320
|
-
min_x = x;
|
|
321
|
-
last_red_value = current_val;
|
|
322
|
-
matching = true;
|
|
323
|
-
}
|
|
324
|
-
} else if (matching) {
|
|
325
|
-
this->node_cluster->add_node(min_x, x - 1, y, last_red_value, offset);
|
|
326
|
-
matching = false;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if (matching) {
|
|
331
|
-
this->node_cluster->add_node(min_x, this->end_x - 1, y, last_red_value, offset);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
/*template <typename M, typename F>
|
|
337
|
-
void run_loop(M* specific_matcher, F&& fetch_color, int offset) {
|
|
338
|
-
int img_h = this->source_bitmap->h();
|
|
339
|
-
int bpp = this->source_bitmap->get_bytes_per_pixel();
|
|
340
|
-
|
|
341
|
-
for (int y = 0; y < img_h; y++) {
|
|
342
|
-
const unsigned char* row_ptr = this->source_bitmap->get_row_ptr(y);
|
|
343
|
-
const unsigned char* p = row_ptr + (this->start_x * bpp);
|
|
344
|
-
|
|
345
|
-
int min_x = 0;
|
|
346
|
-
bool matching = false;
|
|
347
|
-
unsigned char last_red_value = 0;
|
|
348
|
-
|
|
349
|
-
int x = this->start_x;
|
|
350
|
-
|
|
351
|
-
// --- IL TUO SWEET SPOT: UNROLLING A 4 VIE RIFINITO ---
|
|
352
|
-
if (bpp == 4) {
|
|
353
|
-
for (; x <= this->end_x - 4; x += 4) {
|
|
354
|
-
// Leggiamo in sequenza stretta per ottimizzare i register e la cache L1
|
|
355
|
-
unsigned int c0 = fetch_color(p);
|
|
356
|
-
unsigned char v0 = p[0];
|
|
357
|
-
|
|
358
|
-
unsigned int c1 = fetch_color(p + 4);
|
|
359
|
-
unsigned char v1 = p[4];
|
|
360
|
-
|
|
361
|
-
unsigned int c2 = fetch_color(p + 8);
|
|
362
|
-
unsigned char v2 = p[8];
|
|
363
|
-
|
|
364
|
-
unsigned int c3 = fetch_color(p + 12);
|
|
365
|
-
unsigned char v3 = p[12];
|
|
366
|
-
|
|
367
|
-
p += 16; // Spostato qui: avanza di 4 pixel RGBA precisi
|
|
368
|
-
|
|
369
|
-
bool m0 = specific_matcher->match(c0);
|
|
370
|
-
bool m1 = specific_matcher->match(c1);
|
|
371
|
-
bool m2 = specific_matcher->match(c2);
|
|
372
|
-
bool m3 = specific_matcher->match(c3);
|
|
373
|
-
|
|
374
|
-
// Pixel 0
|
|
375
|
-
if (m0) {
|
|
376
|
-
if (!matching) { min_x = x; last_red_value = v0; matching = true; }
|
|
377
|
-
} else if (matching) {
|
|
378
|
-
this->node_cluster->add_node(min_x, x - 1, y, last_red_value, offset);
|
|
379
|
-
matching = false;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// Pixel 1
|
|
383
|
-
if (m1) {
|
|
384
|
-
if (!matching) { min_x = x + 1; last_red_value = v1; matching = true; }
|
|
385
|
-
} else if (matching) {
|
|
386
|
-
this->node_cluster->add_node(min_x, x, y, last_red_value, offset);
|
|
387
|
-
matching = false;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// Pixel 2
|
|
391
|
-
if (m2) {
|
|
392
|
-
if (!matching) { min_x = x + 2; last_red_value = v2; matching = true; }
|
|
393
|
-
} else if (matching) {
|
|
394
|
-
this->node_cluster->add_node(min_x, x + 1, y, last_red_value, offset);
|
|
395
|
-
matching = false;
|
|
396
|
-
}
|
|
203
|
+
} else if (matching) {
|
|
204
|
+
this->node_cluster->add_node(min_x, x - 1, y, last_red_value, offset);
|
|
205
|
+
matching = false;
|
|
206
|
+
}
|
|
397
207
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
} else if (matching) {
|
|
402
|
-
this->node_cluster->add_node(min_x, x + 2, y, last_red_value, offset);
|
|
403
|
-
matching = false;
|
|
404
|
-
}
|
|
208
|
+
if (m1) {
|
|
209
|
+
if (!matching) {
|
|
210
|
+
min_x = x + 1; last_red_value = v1; matching = true;
|
|
405
211
|
}
|
|
406
|
-
|
|
212
|
+
} else if (matching) {
|
|
213
|
+
this->node_cluster->add_node(min_x, x, y, last_red_value, offset);
|
|
214
|
+
matching = false;
|
|
215
|
+
}
|
|
407
216
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
unsigned char current_val = p[0];
|
|
412
|
-
p += bpp;
|
|
413
|
-
|
|
414
|
-
if (specific_matcher->match(color)) {
|
|
415
|
-
if (!matching) {
|
|
416
|
-
min_x = x;
|
|
417
|
-
last_red_value = current_val;
|
|
418
|
-
matching = true;
|
|
419
|
-
}
|
|
420
|
-
} else if (matching) {
|
|
421
|
-
this->node_cluster->add_node(min_x, x - 1, y, last_red_value, offset);
|
|
422
|
-
matching = false;
|
|
217
|
+
if (m2) {
|
|
218
|
+
if (!matching) {
|
|
219
|
+
min_x = x + 2; last_red_value = v2; matching = true;
|
|
423
220
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
this->node_cluster->add_node(min_x, this->end_x - 1, y, last_red_value, offset);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}*/
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
/*
|
|
436
|
-
|
|
437
|
-
#include <cstdint>
|
|
438
|
-
|
|
439
|
-
template <typename M, typename F>
|
|
440
|
-
void run_loop(M* specific_matcher, F&& fetch_color, int offset) {
|
|
441
|
-
int img_h = this->source_bitmap->h();
|
|
442
|
-
int bpp = this->source_bitmap->get_bytes_per_pixel();
|
|
443
|
-
|
|
444
|
-
for (int y = 0; y < img_h; y++) {
|
|
445
|
-
const unsigned char* row_ptr = this->source_bitmap->get_row_ptr(y);
|
|
446
|
-
const unsigned char* p = row_ptr + (this->start_x * bpp);
|
|
447
|
-
|
|
448
|
-
int min_x = 0;
|
|
449
|
-
bool matching = false;
|
|
450
|
-
unsigned char last_red_value = 0;
|
|
451
|
-
|
|
452
|
-
int x = this->start_x;
|
|
453
|
-
|
|
454
|
-
// --- LINEA 1: UNROLLING A 4 VIE (SIMD FRIENDLY, NO DEPENDENCY) ---
|
|
455
|
-
if (bpp == 4) {
|
|
456
|
-
for (; x <= this->end_x - 4; x += 4) {
|
|
457
|
-
// Carichiamo 4 pixel in variabili separate (zero dipendenze tra loro)
|
|
458
|
-
unsigned int c0 = fetch_color(p);
|
|
459
|
-
unsigned int c1 = fetch_color(p + 4);
|
|
460
|
-
unsigned int c2 = fetch_color(p + 8);
|
|
461
|
-
unsigned int c3 = fetch_color(p + 12);
|
|
462
|
-
|
|
463
|
-
unsigned char v0 = p[0];
|
|
464
|
-
unsigned char v1 = p[4];
|
|
465
|
-
unsigned char v2 = p[8];
|
|
466
|
-
unsigned char v3 = p[12];
|
|
467
|
-
|
|
468
|
-
p += 16; // Avanza di 4 pixel (4 * 4 byte)
|
|
469
|
-
|
|
470
|
-
// Eseguiamo il match in parallelo. Il compilatore trasforma questo in istruzioni vettoriali
|
|
471
|
-
bool m0 = specific_matcher->match(c0);
|
|
472
|
-
bool m1 = specific_matcher->match(c1);
|
|
473
|
-
bool m2 = specific_matcher->match(c2);
|
|
474
|
-
bool m3 = specific_matcher->match(c3);
|
|
475
|
-
|
|
476
|
-
// Pixel 0
|
|
477
|
-
if (m0) {
|
|
478
|
-
if (!matching) { min_x = x; last_red_value = v0; matching = true; }
|
|
479
|
-
} else if (matching) {
|
|
480
|
-
this->node_cluster->add_node(min_x, x - 1, y, last_red_value, offset);
|
|
481
|
-
matching = false;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// Pixel 1
|
|
485
|
-
if (m1) {
|
|
486
|
-
if (!matching) { min_x = x + 1; last_red_value = v1; matching = true; }
|
|
487
|
-
} else if (matching) {
|
|
488
|
-
this->node_cluster->add_node(min_x, x, y, last_red_value, offset);
|
|
489
|
-
matching = false;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// Pixel 2
|
|
493
|
-
if (m2) {
|
|
494
|
-
if (!matching) { min_x = x + 2; last_red_value = v2; matching = true; }
|
|
495
|
-
} else if (matching) {
|
|
496
|
-
this->node_cluster->add_node(min_x, x + 1, y, last_red_value, offset);
|
|
497
|
-
matching = false;
|
|
498
|
-
}
|
|
221
|
+
} else if (matching) {
|
|
222
|
+
this->node_cluster->add_node(min_x, x + 1, y, last_red_value, offset);
|
|
223
|
+
matching = false;
|
|
224
|
+
}
|
|
499
225
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
} else if (matching) {
|
|
504
|
-
this->node_cluster->add_node(min_x, x + 2, y, last_red_value, offset);
|
|
505
|
-
matching = false;
|
|
506
|
-
}
|
|
226
|
+
if (m3) {
|
|
227
|
+
if (!matching) {
|
|
228
|
+
min_x = x + 3; last_red_value = v3; matching = true;
|
|
507
229
|
}
|
|
230
|
+
} else if (matching) {
|
|
231
|
+
this->node_cluster->add_node(min_x, x + 2, y, last_red_value, offset);
|
|
232
|
+
matching = false;
|
|
233
|
+
}
|
|
508
234
|
}
|
|
235
|
+
}
|
|
509
236
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
matching = false;
|
|
525
|
-
}
|
|
237
|
+
// remaining pixels (width not a multiple of 4)
|
|
238
|
+
for (; x < this->end_x; x++) {
|
|
239
|
+
unsigned int color = fetch_color(p);
|
|
240
|
+
unsigned char current_val = static_cast<unsigned char>(color);
|
|
241
|
+
p += bpp;
|
|
242
|
+
if (specific_matcher->match(color)) {
|
|
243
|
+
if (!matching) {
|
|
244
|
+
min_x = x;
|
|
245
|
+
last_red_value = current_val;
|
|
246
|
+
matching = true;
|
|
247
|
+
}
|
|
248
|
+
} else if (matching) {
|
|
249
|
+
this->node_cluster->add_node(min_x, x - 1, y, last_red_value, offset);
|
|
250
|
+
matching = false;
|
|
526
251
|
}
|
|
252
|
+
}
|
|
527
253
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
}
|
|
254
|
+
if (matching) {
|
|
255
|
+
this->node_cluster->add_node(min_x, this->end_x - 1, y, last_red_value, offset);
|
|
256
|
+
}
|
|
532
257
|
}
|
|
533
|
-
}
|
|
258
|
+
}
|
|
534
259
|
|
|
535
260
|
public:
|
|
536
261
|
PolygonFinder(Bitmap *bitmap,
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
#include "../../CpuTimer.h"
|
|
19
19
|
|
|
20
20
|
Cluster::Cluster(Finder *finder, int height, int start_x, int end_x)
|
|
21
|
-
:
|
|
21
|
+
: finder_(finder)
|
|
22
22
|
{ tiles_.reserve(2); // only two (left|right)
|
|
23
23
|
this->hub_ = new Hub(height);
|
|
24
24
|
}
|
|
@@ -40,16 +40,16 @@ void Cluster::add(Tile* tile) {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
void Cluster::list_to_string(std::vector<Point
|
|
43
|
+
void Cluster::list_to_string(std::vector<Point> list)
|
|
44
44
|
{ std::cout << "(" << &list << ") ";
|
|
45
|
-
for (Point
|
|
46
|
-
std::cout << point
|
|
45
|
+
for (const Point& point : list) {
|
|
46
|
+
std::cout << point.toString();
|
|
47
47
|
}
|
|
48
48
|
std::cout << std::endl;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
Tile* Cluster::merge_tiles() {
|
|
52
|
-
bool treemap = this->
|
|
52
|
+
bool treemap = this->finder_->options().treemap;
|
|
53
53
|
double tot_inner = 0;
|
|
54
54
|
double tot_outer = 0;
|
|
55
55
|
CpuTimer timer;
|
|
@@ -141,7 +141,7 @@ Tile* Cluster::merge_tiles() {
|
|
|
141
141
|
};
|
|
142
142
|
|
|
143
143
|
Tile* tile = new Tile(
|
|
144
|
-
this->
|
|
144
|
+
this->finder_, tiles_.front()->start_x(), tiles_.back()->end_x(), tiles_.front()->name() + tiles_.back()->name(), b);
|
|
145
145
|
|
|
146
146
|
tile->assign_shapes(new_shapes);
|
|
147
147
|
for (Tile* old_tile : tiles_) {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
class Cluster {
|
|
20
20
|
private:
|
|
21
|
-
Finder *
|
|
21
|
+
Finder *finder_;
|
|
22
22
|
std::vector<Tile*> tiles_;
|
|
23
23
|
Hub *hub_ = nullptr;
|
|
24
24
|
void assign_ancestry(Shape *shape, InnerPolyline* inner_polyline);
|
|
@@ -31,7 +31,8 @@ class Cluster {
|
|
|
31
31
|
Tile* merge_tiles();
|
|
32
32
|
const std::vector<Tile*> tiles() const { return tiles_; }
|
|
33
33
|
Hub* hub() { return hub_; }
|
|
34
|
-
static void list_to_string(std::vector<Point
|
|
34
|
+
static void list_to_string(std::vector<Point> list);
|
|
35
35
|
PartPool parts_pool;
|
|
36
36
|
std::deque<Position> positions_pool;
|
|
37
|
+
const Finder* finder() const { return finder_; };
|
|
37
38
|
};
|
|
@@ -29,7 +29,7 @@ Sequence* Cursor::join_outers()
|
|
|
29
29
|
this->shapes_sequence_,
|
|
30
30
|
outer_joined_polyline);
|
|
31
31
|
|
|
32
|
-
if (
|
|
32
|
+
if (outer_joined_polyline->head->payload == outer_joined_polyline->tail->payload &&
|
|
33
33
|
this->cluster.tiles().front()->left() &&
|
|
34
34
|
this->cluster.tiles().back()->right()) outer_joined_polyline->pop();
|
|
35
35
|
|
|
@@ -151,11 +151,11 @@ std::vector<InnerPolyline*> Cursor::join_inners(Sequence* outer_seq, bool treema
|
|
|
151
151
|
retme_sequence->move_from(*part, [&](QNode<Point>* pos) -> bool {
|
|
152
152
|
Position *position = static_cast<Position*>(pos);
|
|
153
153
|
if (part->is(Part::ADDED) &&
|
|
154
|
-
!(position->payload
|
|
155
|
-
position->payload
|
|
154
|
+
!(position->payload.y >= bounds.min &&
|
|
155
|
+
position->payload.y <= bounds.max)) {
|
|
156
156
|
return(false);
|
|
157
157
|
}
|
|
158
|
-
return(!(polyline->tile->tg_border(
|
|
158
|
+
return(!(polyline->tile->tg_border(position->payload) && position->end_point()->tracked_outer));
|
|
159
159
|
});
|
|
160
160
|
}
|
|
161
161
|
if (retme_sequence->is_not_vertical()) {
|
|
@@ -175,7 +175,7 @@ void Cursor::mark_children(std::vector<EndPoint*>& end_points, const Polyline* o
|
|
|
175
175
|
for (size_t i = 0; i + 1 < end_points.size(); i += 2) {
|
|
176
176
|
const auto& a = end_points[i];
|
|
177
177
|
const auto& b = end_points[i + 1];
|
|
178
|
-
auto [y_min, y_max] = std::minmax(a->get_point()
|
|
178
|
+
auto [y_min, y_max] = std::minmax(a->get_point().y, b->get_point().y);
|
|
179
179
|
for (int y = y_min + 1; y < y_max; ++y) {
|
|
180
180
|
EndPoint* end_point = this->cluster.hub()->get(y);
|
|
181
181
|
if (end_point) {
|
|
@@ -199,9 +199,9 @@ void Cursor::traverse_inner(Part* act_part, std::vector<Part*>& all_parts, Bound
|
|
|
199
199
|
auto [min_it, max_it] = std::minmax_element(
|
|
200
200
|
points.begin(),
|
|
201
201
|
points.end(),
|
|
202
|
-
[](Point
|
|
203
|
-
bounds.min = std::min(bounds.min,
|
|
204
|
-
bounds.max = std::max(bounds.max,
|
|
202
|
+
[](const Point& a, const Point& b) { return a.y < b.y; });
|
|
203
|
+
bounds.min = std::min(bounds.min, min_it->y);
|
|
204
|
+
bounds.max = std::max(bounds.max, max_it->y);
|
|
205
205
|
}
|
|
206
206
|
if (act_part->innerable()) {
|
|
207
207
|
all_parts.push_back(act_part);
|
|
@@ -16,15 +16,15 @@ class Part;
|
|
|
16
16
|
|
|
17
17
|
class EndPoint {
|
|
18
18
|
public:
|
|
19
|
-
EndPoint()
|
|
19
|
+
EndPoint() {}
|
|
20
20
|
|
|
21
|
-
void set_point(Point
|
|
22
|
-
Point
|
|
21
|
+
void set_point(const Point& p) { point_ = p; }
|
|
22
|
+
const Point& get_point() const { return point_; }
|
|
23
23
|
std::vector<Queueable<Point>*>& queues() { return queues_; }
|
|
24
24
|
bool queues_include(Queueable<Point>* q) const;
|
|
25
25
|
bool tracked_outer = false;
|
|
26
26
|
|
|
27
27
|
private:
|
|
28
|
-
Point
|
|
28
|
+
Point point_;
|
|
29
29
|
std::vector<Queueable<Point>*> queues_;
|
|
30
30
|
};
|
|
@@ -35,7 +35,6 @@ class Finder : public Poolable {
|
|
|
35
35
|
Matcher *matcher;
|
|
36
36
|
pf_Options options_;
|
|
37
37
|
std::vector<std::string> input_options;
|
|
38
|
-
Tile* whole_tile = nullptr;
|
|
39
38
|
std::queue<ClippedPolygonFinder*> finders;
|
|
40
39
|
std::mutex finders_mutex;
|
|
41
40
|
std::map<std::string, double> reports;
|
|
@@ -45,6 +44,7 @@ class Finder : public Poolable {
|
|
|
45
44
|
Queue<Tile*> tiles_;
|
|
46
45
|
int maximum_width_;
|
|
47
46
|
int height = 0;
|
|
47
|
+
Tile* whole_tile = nullptr;
|
|
48
48
|
void process_tiles();
|
|
49
49
|
|
|
50
50
|
public:
|
|
@@ -56,4 +56,6 @@ class Finder : public Poolable {
|
|
|
56
56
|
virtual ProcessResult* process_info();
|
|
57
57
|
const pf_Options& options() const { return options_; }
|
|
58
58
|
Queue<Tile*>& tiles() { return tiles_; }
|
|
59
|
+
virtual bool transpose() const { return false; }
|
|
60
|
+
int versus;
|
|
59
61
|
};
|