contrek 1.0.4 → 1.0.6
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 +4 -3
- data/CHANGELOG.md +21 -0
- data/Gemfile.lock +4 -4
- data/README.md +34 -30
- data/Rakefile +3 -0
- data/contrek.gemspec +7 -4
- data/ext/cpp_polygon_finder/PolygonFinder/Makefile +44 -0
- data/ext/cpp_polygon_finder/PolygonFinder/images/sample_10240x10240.png +0 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/Main.cpp +14 -5
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +136 -15
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.h +5 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/CpuTimer.h +44 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/Bitmap.cpp +8 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/Bitmap.h +3 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/FastPngBitmap.cpp +63 -573
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/FastPngBitmap.h +17 -18
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/RemoteFastPngBitmap.cpp +22 -5
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/RemoteFastPngBitmap.h +4 -8
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/spng.c +6980 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/spng.h +537 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/FinderUtils.cpp +101 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/FinderUtils.h +16 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/List.cpp +0 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/List.h +4 -7
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Lists.cpp +13 -13
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Lists.h +5 -7
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.cpp +47 -41
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.h +15 -10
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.cpp +181 -178
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.h +19 -20
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Polygon.h +20 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.cpp +52 -137
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +85 -16
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/RectBounds.h +39 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ClippedPolygonFinder.cpp +14 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ClippedPolygonFinder.h +17 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.cpp +117 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.h +32 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.cpp +344 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.h +46 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/EndPoint.cpp +14 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/EndPoint.h +22 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/FakeCluster.cpp +13 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/FakeCluster.h +17 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.cpp +138 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.h +52 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Hub.cpp +23 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Hub.h +40 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.cpp +70 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.h +47 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/PartPool.cpp +24 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/PartPool.h +23 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.cpp +182 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.h +30 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +108 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +52 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Poolable.cpp +59 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Poolable.h +52 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.cpp +31 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.h +25 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Queue.h +36 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Queueable.h +230 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.cpp +35 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.h +20 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.cpp +26 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.h +23 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.cpp +105 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.h +56 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/Matcher.cpp +3 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/Matcher.h +5 -8
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/RGBMatcher.h +3 -7
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/RGBNotMatcher.cpp +2 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/RGBNotMatcher.h +4 -8
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/ValueNotMatcher.cpp +2 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/ValueNotMatcher.h +3 -7
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/LinearReducer.cpp +23 -15
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/LinearReducer.h +6 -8
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/Reducer.cpp +2 -5
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/Reducer.h +4 -8
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/UniqReducer.cpp +9 -12
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/UniqReducer.h +3 -7
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/VisvalingamReducer.cpp +26 -27
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/VisvalingamReducer.h +76 -87
- data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +64 -32
- data/ext/cpp_polygon_finder/extconf.rb +14 -0
- data/lib/contrek/bitmaps/sample_generator.rb +56 -0
- data/lib/contrek/cpp/cpp_concurrent_finder.rb +9 -0
- data/lib/contrek/finder/bounds.rb +17 -0
- data/lib/contrek/finder/concurrent/cluster.rb +2 -2
- data/lib/contrek/finder/concurrent/cursor.rb +8 -8
- data/lib/contrek/finder/concurrent/finder.rb +10 -9
- data/lib/contrek/finder/concurrent/part.rb +2 -2
- data/lib/contrek/finder/concurrent/partitionable.rb +1 -1
- data/lib/contrek/finder/concurrent/polyline.rb +17 -15
- data/lib/contrek/finder/concurrent/sequence.rb +11 -0
- data/lib/contrek/finder/concurrent/tile.rb +3 -3
- data/lib/contrek/finder/node_cluster.rb +16 -8
- data/lib/contrek/finder/polygon_finder.rb +1 -4
- data/lib/contrek/version.rb +1 -1
- data/lib/contrek.rb +9 -1
- metadata +62 -15
- data/ext/cpp_polygon_finder/PolygonFinder/.cproject +0 -136
- data/ext/cpp_polygon_finder/PolygonFinder/.project +0 -27
- data/ext/cpp_polygon_finder/PolygonFinder/.settings/org.eclipse.ltk.core.refactoring.prefs +0 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/PngBitmap.cpp +0 -48
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/PngBitmap.h +0 -32
|
@@ -6,198 +6,113 @@
|
|
|
6
6
|
* Copyright 2025 Emanuele Cesaroni
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
#include <iostream>
|
|
11
10
|
#include <list>
|
|
12
11
|
#include <map>
|
|
13
12
|
#include <ctime>
|
|
14
13
|
#include <typeinfo>
|
|
15
14
|
#include <string>
|
|
16
|
-
#include <ctime>
|
|
17
15
|
#include <vector>
|
|
16
|
+
#include <utility>
|
|
18
17
|
#include "PolygonFinder.h"
|
|
19
18
|
#include "../bitmaps/Bitmap.h"
|
|
20
19
|
#include "../matchers/Matcher.h"
|
|
21
20
|
#include "../matchers/RGBMatcher.h"
|
|
21
|
+
#include "../matchers/RGBNotMatcher.h"
|
|
22
22
|
#include "optionparser.h"
|
|
23
23
|
#include "NodeCluster.h"
|
|
24
24
|
#include "Node.h"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
#include "FinderUtils.h"
|
|
26
|
+
|
|
27
|
+
PolygonFinder::PolygonFinder(Bitmap *bitmap,
|
|
28
|
+
Matcher *matcher,
|
|
29
|
+
Bitmap *test_bitmap,
|
|
30
|
+
std::vector<std::string> *options,
|
|
31
|
+
int start_x,
|
|
32
|
+
int end_x)
|
|
33
|
+
: source_bitmap(bitmap),
|
|
34
|
+
matcher(matcher),
|
|
35
|
+
start_x(start_x),
|
|
36
|
+
end_x(end_x == -1 ? bitmap->w() : end_x)
|
|
37
|
+
{ this->rgb_matcher = dynamic_cast<RGBMatcher*>(matcher);
|
|
38
|
+
if (options != nullptr) FinderUtils::sanitize_options(this->options, options);
|
|
39
|
+
this->node_cluster = new NodeCluster(source_bitmap->h(), source_bitmap->w(), &this->options);
|
|
31
40
|
|
|
32
41
|
//= SCAN ==============//
|
|
33
|
-
|
|
42
|
+
cpu_timer.start();
|
|
34
43
|
scan();
|
|
35
|
-
reports["scan"] =
|
|
44
|
+
reports["scan"] = cpu_timer.stop();
|
|
36
45
|
//=====================//
|
|
37
46
|
|
|
38
47
|
//= BUILD_TANGS_SEQUENCE ===//
|
|
39
|
-
|
|
48
|
+
cpu_timer.start();
|
|
40
49
|
node_cluster->build_tangs_sequence();
|
|
41
|
-
reports["build_tangs_sequence"] =
|
|
50
|
+
reports["build_tangs_sequence"] = cpu_timer.stop();
|
|
42
51
|
//=====================//
|
|
43
52
|
|
|
44
53
|
//= PLOT ===//
|
|
45
|
-
|
|
54
|
+
cpu_timer.start();
|
|
46
55
|
node_cluster->plot(this->options.versus);
|
|
47
|
-
reports["plot"] =
|
|
56
|
+
reports["plot"] = cpu_timer.stop();
|
|
48
57
|
//=====================//
|
|
49
58
|
|
|
50
59
|
//= COMPRESS_COORDS ===//
|
|
51
|
-
|
|
52
|
-
node_cluster->compress_coords(this->options);
|
|
53
|
-
reports["compress"] =
|
|
60
|
+
cpu_timer.start();
|
|
61
|
+
node_cluster->compress_coords(this->node_cluster->polygons, this->options);
|
|
62
|
+
reports["compress"] = cpu_timer.stop();
|
|
54
63
|
//=====================//
|
|
55
64
|
reports["total"] = reports["scan"] + reports["build_tangs_sequence"] + reports["plot"] + reports["compress"];
|
|
56
65
|
}
|
|
57
66
|
|
|
58
67
|
std::list<ShapeLine*> *PolygonFinder::get_shapelines() {
|
|
59
68
|
std::list<ShapeLine*> *sll = new std::list<ShapeLine*>();
|
|
60
|
-
for (int line = 0; line < this->node_cluster->height; line++)
|
|
61
|
-
|
|
62
|
-
|
|
69
|
+
for (int line = 0; line < this->node_cluster->height; line++) {
|
|
70
|
+
for (Node& node : this->node_cluster->vert_nodes[line]) {
|
|
71
|
+
ShapeLine *sl = new ShapeLine({node.min_x, node.max_x, node.y});
|
|
63
72
|
sll->push_back(sl);
|
|
64
73
|
}
|
|
65
74
|
}
|
|
66
|
-
return
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
void PolygonFinder::sanitize_options(std::vector<std::string> *incoming_options)
|
|
70
|
-
{ std::vector<char*> argv0;
|
|
71
|
-
for (const auto& arg : *incoming_options)
|
|
72
|
-
argv0.push_back((char*)arg.data());
|
|
73
|
-
argv0.push_back(nullptr);
|
|
74
|
-
char** argv = &argv0[0];
|
|
75
|
-
int argc = argv0.size() -1;
|
|
76
|
-
|
|
77
|
-
enum optionIndex { COMPRESS_UNIQ, VERSUS, COMPRESS_VISVALINGAM, COMPRESS_LINEAR, COMPRESS_VISVALINGAM_TOLERANCE, TREEMAP};
|
|
78
|
-
const option::Descriptor usage[] = {
|
|
79
|
-
// {UNKNOWN, 0,"" , "" ,option::Arg::None, 0},
|
|
80
|
-
{COMPRESS_VISVALINGAM, 0, "" , "compress_visvalingam", option::Arg::None, 0},
|
|
81
|
-
{COMPRESS_LINEAR, 0, "" , "compress_linear", option::Arg::None, 0},
|
|
82
|
-
{COMPRESS_VISVALINGAM_TOLERANCE, 0, "" , "compress_visvalingam_tolerance", option::Arg::Optional, 0},
|
|
83
|
-
{COMPRESS_UNIQ, 0, "", "compress_uniq", option::Arg::None, 0},
|
|
84
|
-
{TREEMAP, 0, "", "treemap", option::Arg::None, 0},
|
|
85
|
-
{VERSUS, 0, "v", "versus", option::Arg::Optional, 0},
|
|
86
|
-
{0, 0, 0, 0, 0, 0}
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
option::Stats stats(usage, argc, argv);
|
|
90
|
-
option::Option ioptions[stats.options_max], buffer[stats.buffer_max];
|
|
91
|
-
option::Parser parse(usage, argc, argv, ioptions, buffer);
|
|
92
|
-
|
|
93
|
-
if (parse.error()) return;
|
|
94
|
-
// VERSUS
|
|
95
|
-
if (ioptions[VERSUS].count() > 0)
|
|
96
|
-
{ for (option::Option* opt = ioptions[VERSUS]; opt; opt = opt->next())
|
|
97
|
-
{ std::string opts = opt->arg;
|
|
98
|
-
this->options.versus = (opts.compare("a") == 0 ? Node::A : Node::O);
|
|
99
|
-
break;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
// COMPRESS UNIQ
|
|
103
|
-
if (ioptions[COMPRESS_UNIQ].count() > 0)
|
|
104
|
-
{ this->options.compress_uniq = true;
|
|
105
|
-
}
|
|
106
|
-
// TREEMAP
|
|
107
|
-
if (ioptions[TREEMAP].count() > 0)
|
|
108
|
-
{ this->options.treemap = true;
|
|
109
|
-
}
|
|
110
|
-
// COMPRESS LINEAR
|
|
111
|
-
if (ioptions[COMPRESS_LINEAR].count() > 0)
|
|
112
|
-
{ this->options.compress_linear = true;
|
|
113
|
-
}
|
|
114
|
-
// COMPRESS UNIQ
|
|
115
|
-
if (ioptions[COMPRESS_VISVALINGAM].count() > 0)
|
|
116
|
-
{ this->options.compress_visvalingam = true;
|
|
117
|
-
}
|
|
118
|
-
if (ioptions[COMPRESS_VISVALINGAM_TOLERANCE].count() > 0)
|
|
119
|
-
{ this->options.compress_visvalingam = true;
|
|
120
|
-
for (option::Option* opt = ioptions[COMPRESS_VISVALINGAM_TOLERANCE]; opt; opt = opt->next())
|
|
121
|
-
{ std::string opts = opt->arg;
|
|
122
|
-
this->options.compress_visvalingam_tolerance = strtof(opt->arg, 0);
|
|
123
|
-
break;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
/*std::cout << "-----------" << std::endl;
|
|
127
|
-
std::cout << "versus" << this->options.versus << std::endl;
|
|
128
|
-
std::cout << "uniq" << this->options.compress_uniq << std::endl;
|
|
129
|
-
std::cout << "linear" << this->options.compress_linear << std::endl;
|
|
130
|
-
std::cout << "visvalingam" << this->options.compress_visvalingam << std::endl;
|
|
131
|
-
std::cout << this->options.compress_visvalingam_tolerance << std::endl;
|
|
132
|
-
std::cout << "-----------" << std::endl;*/
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
void PolygonFinder::start_timer() {
|
|
136
|
-
timer_start = std::clock();
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
double PolygonFinder::end_timer() {
|
|
140
|
-
std::clock_t c_end = std::clock();
|
|
141
|
-
return 1000.0 * (c_end - timer_start) / CLOCKS_PER_SEC;
|
|
75
|
+
return sll;
|
|
142
76
|
}
|
|
143
77
|
|
|
144
78
|
PolygonFinder::~PolygonFinder() {
|
|
79
|
+
delete this->node_cluster;
|
|
145
80
|
}
|
|
146
81
|
|
|
147
82
|
void PolygonFinder::scan() {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (
|
|
159
|
-
|
|
160
|
-
last_color = color;
|
|
161
|
-
matching = true;
|
|
162
|
-
if (x == (this->source_bitmap->w() - 1) )
|
|
163
|
-
{ max_x = x;
|
|
164
|
-
this->node_cluster->add_node(new Node(min_x, max_x, y, last_color));
|
|
165
|
-
matching = false;
|
|
166
|
-
}
|
|
167
|
-
} else {
|
|
168
|
-
if (!match && matching == true)
|
|
169
|
-
{ max_x = x - 1;
|
|
170
|
-
this->node_cluster->add_node(new Node(min_x, max_x, y, last_color));
|
|
171
|
-
matching = false;
|
|
172
|
-
} else {
|
|
173
|
-
if (x == (this->source_bitmap->w()-1) && matching == true)
|
|
174
|
-
{ max_x = x;
|
|
175
|
-
this->node_cluster->add_node(new Node(min_x, max_x, y, last_color));
|
|
176
|
-
matching = false;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
83
|
+
int bpp = this->source_bitmap->get_bytes_per_pixel();
|
|
84
|
+
|
|
85
|
+
RGBMatcher* rgb_m = dynamic_cast<RGBMatcher*>(this->matcher);
|
|
86
|
+
|
|
87
|
+
if (bpp == 1) {
|
|
88
|
+
auto fetcher = [](const unsigned char* p) { return static_cast<unsigned int>(p[0]); };
|
|
89
|
+
if (rgb_m) run_loop(rgb_m, fetcher);
|
|
90
|
+
else run_loop(this->matcher, fetcher);
|
|
91
|
+
} else {
|
|
92
|
+
auto fetcher = [](const unsigned char* p) { return p[0] | (p[1] << 8) | (p[2] << 16); };
|
|
93
|
+
if (rgb_m) run_loop(rgb_m, fetcher);
|
|
94
|
+
else run_loop(this->matcher, fetcher);
|
|
180
95
|
}
|
|
181
|
-
}
|
|
182
96
|
}
|
|
183
97
|
|
|
184
98
|
ProcessResult* PolygonFinder::process_info() {
|
|
185
99
|
ProcessResult *pr = new ProcessResult();
|
|
186
|
-
pr->groups = this->node_cluster->sequences
|
|
187
|
-
pr->polygons = this->node_cluster->polygons;
|
|
188
|
-
pr->benchmarks = this->reports;
|
|
100
|
+
pr->groups = this->node_cluster->sequences.size();
|
|
101
|
+
pr->polygons = std::move(this->node_cluster->polygons);
|
|
102
|
+
pr->benchmarks = std::move(this->reports);
|
|
189
103
|
pr->treemap = this->node_cluster->treemap;
|
|
190
104
|
|
|
191
|
-
if (typeid(*this->source_bitmap) == typeid(Bitmap))
|
|
105
|
+
if (this->node_cluster->options->named_sequences && typeid(*this->source_bitmap) == typeid(Bitmap))
|
|
192
106
|
{ std::string sequence;
|
|
193
107
|
int n = 0;
|
|
194
|
-
for (
|
|
195
|
-
|
|
196
|
-
for (
|
|
197
|
-
|
|
108
|
+
for (const auto& seq_list : this->node_cluster->sequences) {
|
|
109
|
+
std::string seq;
|
|
110
|
+
for (Node* node : seq_list) {
|
|
111
|
+
seq += node->name;
|
|
198
112
|
}
|
|
199
113
|
if (n != 0) sequence += '-';
|
|
200
114
|
sequence += seq;
|
|
115
|
+
n++;
|
|
201
116
|
}
|
|
202
117
|
pr->named_sequence = sequence;
|
|
203
118
|
}
|
|
@@ -6,15 +6,20 @@
|
|
|
6
6
|
* Copyright 2025 Emanuele Cesaroni
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
#
|
|
10
|
-
#define POLYGONFINDER_H_
|
|
11
|
-
|
|
9
|
+
#pragma once
|
|
12
10
|
#include <list>
|
|
13
11
|
#include <vector>
|
|
14
|
-
#include "Node.h"
|
|
15
12
|
#include <ctime>
|
|
16
13
|
#include <string>
|
|
17
14
|
#include <map>
|
|
15
|
+
#include <iostream>
|
|
16
|
+
#include <utility>
|
|
17
|
+
#include "../bitmaps/Bitmap.h"
|
|
18
|
+
#include "NodeCluster.h"
|
|
19
|
+
#include "Node.h"
|
|
20
|
+
#include "Polygon.h"
|
|
21
|
+
#include "Node.h"
|
|
22
|
+
#include "../CpuTimer.h"
|
|
18
23
|
|
|
19
24
|
class Bitmap;
|
|
20
25
|
class Matcher;
|
|
@@ -33,37 +38,101 @@ struct pf_Options {
|
|
|
33
38
|
bool compress_uniq = false;
|
|
34
39
|
bool compress_linear = false;
|
|
35
40
|
bool compress_visvalingam = false;
|
|
41
|
+
bool named_sequences = false;
|
|
42
|
+
bool bounds = false;
|
|
36
43
|
float compress_visvalingam_tolerance = 10.0;
|
|
44
|
+
int number_of_tiles = 1;
|
|
45
|
+
std::string get_alpha_versus() {
|
|
46
|
+
return(versus == Node::A ? "a" : "o");
|
|
47
|
+
}
|
|
37
48
|
};
|
|
38
49
|
struct ProcessResult {
|
|
39
50
|
int groups;
|
|
40
51
|
std::map<std::string, double> benchmarks;
|
|
41
|
-
std::list<
|
|
52
|
+
std::list<Polygon> polygons;
|
|
42
53
|
std::string named_sequence;
|
|
43
|
-
std::
|
|
54
|
+
std::vector<std::pair<int, int>> treemap;
|
|
55
|
+
|
|
56
|
+
void print_polygons() {
|
|
57
|
+
int counter = 0;
|
|
58
|
+
for (const auto& polygon : polygons) {
|
|
59
|
+
std::cout << counter << " - " << "outer" << "\n";
|
|
60
|
+
for (const Point* p : polygon.outer) std::cout << p->toString();
|
|
61
|
+
bool first = true;
|
|
62
|
+
for (const auto& seq : polygon.inner) {
|
|
63
|
+
if (!first) std::cout << "\n";
|
|
64
|
+
first = false;
|
|
65
|
+
for (const Point* p : seq) std::cout << p->toString();
|
|
66
|
+
}
|
|
67
|
+
std::cout << "\n";
|
|
68
|
+
counter++;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
void print_info() {
|
|
73
|
+
for (const auto& [key, value] : benchmarks) {
|
|
74
|
+
std::cout << key << ": " << value << ", ";
|
|
75
|
+
}
|
|
76
|
+
std::cout << std::endl;
|
|
77
|
+
}
|
|
44
78
|
};
|
|
45
79
|
|
|
46
80
|
class PolygonFinder {
|
|
81
|
+
protected:
|
|
82
|
+
int start_x;
|
|
83
|
+
int end_x;
|
|
84
|
+
|
|
47
85
|
private:
|
|
48
86
|
Bitmap *source_bitmap;
|
|
49
87
|
Matcher *matcher;
|
|
88
|
+
RGBMatcher* rgb_matcher;
|
|
50
89
|
NodeCluster *node_cluster;
|
|
51
90
|
pf_Options options;
|
|
52
91
|
std::map<std::string, double> reports;
|
|
53
|
-
void start_timer();
|
|
54
|
-
double end_timer();
|
|
55
92
|
void scan();
|
|
56
|
-
|
|
57
|
-
|
|
93
|
+
CpuTimer cpu_timer;
|
|
94
|
+
|
|
95
|
+
template <typename M, typename F>
|
|
96
|
+
void run_loop(M* specific_matcher, F&& fetch_color) {
|
|
97
|
+
int img_h = this->source_bitmap->h();
|
|
98
|
+
int bpp = this->source_bitmap->get_bytes_per_pixel();
|
|
99
|
+
for (int y = 0; y < img_h; y++) {
|
|
100
|
+
const unsigned char* row_ptr = this->source_bitmap->get_row_ptr(y);
|
|
101
|
+
const unsigned char* p = row_ptr + (this->start_x * bpp);
|
|
102
|
+
int min_x = 0;
|
|
103
|
+
bool matching = false;
|
|
104
|
+
unsigned char last_red_value = 0;
|
|
105
|
+
for (int x = this->start_x; x < this->end_x; x++) {
|
|
106
|
+
unsigned int color = fetch_color(p);
|
|
107
|
+
unsigned char current_val = p[0];
|
|
108
|
+
p += bpp;
|
|
109
|
+
if (specific_matcher->match(color)) {
|
|
110
|
+
if (!matching) {
|
|
111
|
+
min_x = x;
|
|
112
|
+
last_red_value = current_val;
|
|
113
|
+
matching = true;
|
|
114
|
+
}
|
|
115
|
+
if (x == this->end_x - 1) {
|
|
116
|
+
this->node_cluster->add_node(min_x, x, y, last_red_value);
|
|
117
|
+
matching = false;
|
|
118
|
+
}
|
|
119
|
+
} else if (matching) {
|
|
120
|
+
this->node_cluster->add_node(min_x, x - 1, y, last_red_value);
|
|
121
|
+
matching = false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
58
126
|
|
|
59
127
|
public:
|
|
60
|
-
PolygonFinder(Bitmap *bitmap,
|
|
128
|
+
PolygonFinder(Bitmap *bitmap,
|
|
129
|
+
Matcher *matcher,
|
|
130
|
+
Bitmap *test_bitmap,
|
|
131
|
+
std::vector<std::string> *options = nullptr,
|
|
132
|
+
int start_x = 0,
|
|
133
|
+
int end_x = -1);
|
|
61
134
|
ProcessResult* process_info();
|
|
62
135
|
std::list<ShapeLine*> *get_shapelines();
|
|
63
136
|
virtual ~PolygonFinder();
|
|
137
|
+
const NodeCluster* get_cluster() const { return this->node_cluster; }
|
|
64
138
|
};
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
#endif /* POLYGONFINDER_H_ */
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* RectBounds.h
|
|
3
|
+
*
|
|
4
|
+
* Created on: 23 nov 2025
|
|
5
|
+
* Author: ema
|
|
6
|
+
* Copyright 2025 Emanuele Cesaroni
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#pragma once
|
|
10
|
+
#include <limits>
|
|
11
|
+
#include <algorithm>
|
|
12
|
+
|
|
13
|
+
struct RectBounds {
|
|
14
|
+
int min_x = std::numeric_limits<int>::max();
|
|
15
|
+
int max_x = std::numeric_limits<int>::min();
|
|
16
|
+
int min_y = std::numeric_limits<int>::max();
|
|
17
|
+
int max_y = std::numeric_limits<int>::min();
|
|
18
|
+
|
|
19
|
+
static RectBounds empty() {
|
|
20
|
+
return RectBounds{};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
inline RectBounds& expand(int x, int y) {
|
|
24
|
+
if (x < min_x) min_x = x;
|
|
25
|
+
if (x > max_x) max_x = x;
|
|
26
|
+
if (y < min_y) min_y = y;
|
|
27
|
+
if (y > max_y) max_y = y;
|
|
28
|
+
return *this;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
inline bool is_empty() const {
|
|
32
|
+
return min_x == std::numeric_limits<int>::max();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
inline int width() const {
|
|
36
|
+
if (is_empty()) return 0;
|
|
37
|
+
return(max_x - min_x);
|
|
38
|
+
}
|
|
39
|
+
};
|
data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ClippedPolygonFinder.cpp
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* ClippedPolygonFinder.cpp
|
|
3
|
+
*
|
|
4
|
+
* Created on: 23 nov 2025
|
|
5
|
+
* Author: ema
|
|
6
|
+
* Copyright 2025 Emanuele Cesaroni
|
|
7
|
+
*/
|
|
8
|
+
#include <string>
|
|
9
|
+
#include <vector>
|
|
10
|
+
#include "ClippedPolygonFinder.h"
|
|
11
|
+
|
|
12
|
+
ClippedPolygonFinder::ClippedPolygonFinder(Bitmap *bitmap, Matcher *matcher, int bitmap_start_x, int bitmap_end_x, std::vector<std::string> *options)
|
|
13
|
+
: PolygonFinder(bitmap, matcher, nullptr, options, bitmap_start_x, bitmap_end_x) {
|
|
14
|
+
}
|
data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ClippedPolygonFinder.h
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* ClippedPolygonFinder.h
|
|
3
|
+
*
|
|
4
|
+
* Created on: 23 nov 2025
|
|
5
|
+
* Author: ema
|
|
6
|
+
* Copyright 2025 Emanuele Cesaroni
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#pragma once
|
|
10
|
+
#include <string>
|
|
11
|
+
#include <vector>
|
|
12
|
+
#include "../PolygonFinder.h"
|
|
13
|
+
|
|
14
|
+
class ClippedPolygonFinder : public PolygonFinder {
|
|
15
|
+
public:
|
|
16
|
+
ClippedPolygonFinder(Bitmap *bitmap, Matcher *matcher, int bm_start_x, int bm_end_x, std::vector<std::string> *options = nullptr);
|
|
17
|
+
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Cluster.cpp
|
|
3
|
+
*
|
|
4
|
+
* Created on: 23 nov 2025
|
|
5
|
+
* Author: ema
|
|
6
|
+
* Copyright 2025 Emanuele Cesaroni
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#include <vector>
|
|
10
|
+
#include <list>
|
|
11
|
+
#include <iostream>
|
|
12
|
+
#include "Cluster.h"
|
|
13
|
+
#include "Shape.h"
|
|
14
|
+
#include "Polyline.h"
|
|
15
|
+
#include "Sequence.h"
|
|
16
|
+
#include "Cursor.h"
|
|
17
|
+
#include "../../CpuTimer.h"
|
|
18
|
+
|
|
19
|
+
Cluster::Cluster(Finder *finder, int height, int width)
|
|
20
|
+
: finder(finder)
|
|
21
|
+
{ tiles_.reserve(2); // only two (left|right)
|
|
22
|
+
this->hub_ = new Hub(height, width);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
Cluster::~Cluster() {
|
|
26
|
+
for (Tile* tile : tiles_) {
|
|
27
|
+
delete tile;
|
|
28
|
+
}
|
|
29
|
+
delete this->hub_;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
void Cluster::add(Tile* tile) {
|
|
33
|
+
Tile* last_tile = tiles_.empty() ? nullptr : tiles_.back();
|
|
34
|
+
tiles_.push_back(tile);
|
|
35
|
+
tile->cluster = this;
|
|
36
|
+
if (last_tile) {
|
|
37
|
+
last_tile->next = last_tile->circular_next = tile;
|
|
38
|
+
tile->prev = tile->circular_next = last_tile;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
void Cluster::list_to_string(std::vector<Point*> list)
|
|
43
|
+
{ std::cout << "(" << &list << ") ";
|
|
44
|
+
for (Point* point : list) {
|
|
45
|
+
std::cout << point->toString();
|
|
46
|
+
}
|
|
47
|
+
std::cout << std::endl;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
Tile* Cluster::merge_tiles() {
|
|
51
|
+
double tot_inner = 0;
|
|
52
|
+
double tot_outer = 0;
|
|
53
|
+
CpuTimer timer;
|
|
54
|
+
std::list<Shape*> shapes;
|
|
55
|
+
|
|
56
|
+
timer.start();
|
|
57
|
+
for (Tile* tile : tiles_) {
|
|
58
|
+
for (Shape *shape : tile->shapes()) {
|
|
59
|
+
if (shape->outer_polyline->is_on(Polyline::TRACKED_OUTER) || shape->outer_polyline->width() == 0) continue;
|
|
60
|
+
if (shape->outer_polyline->boundary())
|
|
61
|
+
{ shape->outer_polyline->partition();
|
|
62
|
+
shape->outer_polyline->precalc();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
tot_outer += timer.stop();
|
|
67
|
+
|
|
68
|
+
for (Tile* tile : tiles_) {
|
|
69
|
+
std::list<Shape*>& src = tile->shapes();
|
|
70
|
+
for (auto it = src.begin(); it != src.end(); )
|
|
71
|
+
{ Shape* shape = *it;
|
|
72
|
+
if (shape->outer_polyline->is_on(Polyline::TRACKED_OUTER) || shape->outer_polyline->width() == 0)
|
|
73
|
+
{ it++;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (shape->outer_polyline->boundary() && !shape->outer_polyline->next_tile_eligible_shapes().empty()) {
|
|
78
|
+
Sequence* new_outer = nullptr;
|
|
79
|
+
std::list<std::vector<Point*>> new_inners = shape->inner_polylines;
|
|
80
|
+
Cursor cursor(*this, shape);
|
|
81
|
+
timer.start();
|
|
82
|
+
new_outer = cursor.join_outers();
|
|
83
|
+
tot_outer += timer.stop();
|
|
84
|
+
|
|
85
|
+
timer.start();
|
|
86
|
+
std::vector<Sequence*> new_inner_sequences = cursor.join_inners(new_outer);
|
|
87
|
+
tot_inner += timer.stop();
|
|
88
|
+
|
|
89
|
+
for (Sequence* s : new_inner_sequences) {
|
|
90
|
+
new_inners.push_back(s->to_vector());
|
|
91
|
+
delete s;
|
|
92
|
+
}
|
|
93
|
+
for (auto s : cursor.orphan_inners()) {
|
|
94
|
+
new_inners.push_back(s);
|
|
95
|
+
}
|
|
96
|
+
Polyline* polyline = new Polyline(tile, new_outer->to_vector());
|
|
97
|
+
Shape* shape = new Shape(polyline, new_inners);
|
|
98
|
+
shapes.push_back(shape);
|
|
99
|
+
polyline->shape = shape;
|
|
100
|
+
it++;
|
|
101
|
+
} else {
|
|
102
|
+
shapes.push_back(shape);
|
|
103
|
+
it = src.erase(it);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
double past_tot_outer = tiles_.front()->benchmarks.outer + tiles_.back()->benchmarks.outer;
|
|
108
|
+
double past_tot_inner = tiles_.front()->benchmarks.inner + tiles_.back()->benchmarks.inner;
|
|
109
|
+
Benchmarks b{
|
|
110
|
+
tot_outer + past_tot_outer,
|
|
111
|
+
tot_inner + past_tot_inner
|
|
112
|
+
};
|
|
113
|
+
Tile* tile = new Tile(this->finder, tiles_.front()->start_x(), tiles_.back()->end_x(), tiles_.front()->name() + tiles_.back()->name(), b);
|
|
114
|
+
tile->assign_shapes(shapes);
|
|
115
|
+
return(tile);
|
|
116
|
+
}
|
|
117
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Cluster.h
|
|
3
|
+
*
|
|
4
|
+
* Created on: 23 nov 2025
|
|
5
|
+
* Author: ema
|
|
6
|
+
* Copyright 2025 Emanuele Cesaroni
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#pragma once
|
|
10
|
+
#include <vector>
|
|
11
|
+
#include <deque>
|
|
12
|
+
#include "Finder.h"
|
|
13
|
+
#include "Cluster.h"
|
|
14
|
+
#include "Hub.h"
|
|
15
|
+
#include "PartPool.h"
|
|
16
|
+
|
|
17
|
+
class Cluster {
|
|
18
|
+
private:
|
|
19
|
+
Finder *finder;
|
|
20
|
+
std::vector<Tile*> tiles_;
|
|
21
|
+
Hub *hub_ = nullptr;
|
|
22
|
+
public:
|
|
23
|
+
Cluster(Finder *finder, int height, int width);
|
|
24
|
+
virtual ~Cluster();
|
|
25
|
+
void add(Tile* tile);
|
|
26
|
+
Tile* merge_tiles();
|
|
27
|
+
const std::vector<Tile*> tiles() const { return tiles_; }
|
|
28
|
+
Hub* hub() { return hub_; }
|
|
29
|
+
static void list_to_string(std::vector<Point*> list);
|
|
30
|
+
PartPool parts_pool;
|
|
31
|
+
std::deque<Position> positions_pool;
|
|
32
|
+
};
|