contrek 1.2.9 → 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/Gemfile.lock +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +14 -22
- 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 -12
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +10 -58
- 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 +2 -0
- 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 +12 -13
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +4 -4
- 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 +8 -5
- 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 +14 -14
- data/lib/contrek/bitmaps/chunky_bitmap.rb +11 -0
- data/lib/contrek/finder/concurrent/cluster.rb +1 -1
- data/lib/contrek/finder/concurrent/finder.rb +4 -0
- data/lib/contrek/finder/concurrent/merger.rb +1 -0
- data/lib/contrek/finder/concurrent/part.rb +11 -0
- data/lib/contrek/finder/concurrent/partitionable.rb +31 -17
- data/lib/contrek/finder/concurrent/vertical_merger.rb +4 -0
- data/lib/contrek/finder/polygon_finder.rb +2 -1
- data/lib/contrek/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 58d88411970256b3edc37da05dd9304aaa4593b320e7d73db5966b69d403c4cf
|
|
4
|
+
data.tar.gz: 6a05687f7ffba4b22eb7ebf02abf2a622931bc3250968fa785fb13720036118e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7150e06efce7580fdefd55725db0de52e2805b909e800679a0f99481c3e52333209d1b5ceb750c1fc63a28fa6aaaad7f7662d3baf3ebf377b29cfe4dacf6d19d
|
|
7
|
+
data.tar.gz: 988e85fd99234df2b3cd0e8bec0d8f68ba0f631111a3fda62e114e185dd1619589223266b5e3db71a2a5c478d2871f862209489df997a13a9da866b84718c609
|
data/Gemfile.lock
CHANGED
|
@@ -60,16 +60,16 @@ void Tests::test_a()
|
|
|
60
60
|
std::vector<int> array_compare;
|
|
61
61
|
|
|
62
62
|
for (const auto& x : o->polygons)
|
|
63
|
-
{ for (const Point
|
|
64
|
-
array_compare.push_back(p
|
|
65
|
-
array_compare.push_back(p
|
|
63
|
+
{ for (const Point& p : x.outer) {
|
|
64
|
+
array_compare.push_back(p.x);
|
|
65
|
+
array_compare.push_back(p.y);
|
|
66
66
|
}
|
|
67
67
|
if (outer_array != array_compare) throw std::runtime_error("Wrong OUTER results!");
|
|
68
68
|
array_compare.clear();
|
|
69
69
|
for (const auto& z : x.inner)
|
|
70
|
-
{ for (const Point
|
|
71
|
-
{ array_compare.push_back(y
|
|
72
|
-
array_compare.push_back(y
|
|
70
|
+
{ for (const Point& y : z)
|
|
71
|
+
{ array_compare.push_back(y.x);
|
|
72
|
+
array_compare.push_back(y.y);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
if (inner_array != array_compare) throw std::runtime_error("Wrong INNER results!");
|
|
@@ -97,9 +97,9 @@ void Tests::test_b()
|
|
|
97
97
|
|
|
98
98
|
void Tests::test_c()
|
|
99
99
|
{ Sequence sequence;
|
|
100
|
-
Point
|
|
101
|
-
Point
|
|
102
|
-
Point
|
|
100
|
+
Point p1{1, 1};
|
|
101
|
+
Point p2{2, 2};
|
|
102
|
+
Point p3{3, 3};
|
|
103
103
|
|
|
104
104
|
Hub* hub = new Hub(4);
|
|
105
105
|
|
|
@@ -114,7 +114,7 @@ void Tests::test_c()
|
|
|
114
114
|
if (sequence.size != 3) throw std::runtime_error("Wrong sequence size");
|
|
115
115
|
|
|
116
116
|
// iterator() initially gives head
|
|
117
|
-
Point
|
|
117
|
+
const Point& head = sequence.head->payload;
|
|
118
118
|
if (head != p1) throw std::runtime_error("Wrong head");
|
|
119
119
|
if (sequence.iterator()->payload != p1) throw std::runtime_error("Wrong iterator to head");
|
|
120
120
|
if (sequence.iterator() != pos1) throw std::runtime_error("Wrong iterator to head");
|
|
@@ -135,10 +135,6 @@ void Tests::test_c()
|
|
|
135
135
|
sequence.rewind();
|
|
136
136
|
if (sequence.iterator()->payload != p1) throw std::runtime_error("Wrong iterator to head");
|
|
137
137
|
|
|
138
|
-
delete p1;
|
|
139
|
-
delete p2;
|
|
140
|
-
delete p3;
|
|
141
|
-
|
|
142
138
|
delete hub;
|
|
143
139
|
|
|
144
140
|
delete pos1;
|
|
@@ -348,10 +344,8 @@ void stream_png_image(const std::string& filepath, uint32_t stripe_height, bool
|
|
|
348
344
|
ProcessResult *result = polygon_finder.process_info();
|
|
349
345
|
if (result) {
|
|
350
346
|
std::cout << "stripe " << stripe_count << ": found polygons " << result->groups << std::endl;
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
vmerger.add_tile(*safe_result);
|
|
354
|
-
delete result;
|
|
347
|
+
result_clones.push_back(result);
|
|
348
|
+
vmerger.add_tile(*result);
|
|
355
349
|
}
|
|
356
350
|
stripe_count++;
|
|
357
351
|
}
|
|
@@ -467,10 +461,8 @@ void stream_progressive_png_image(const std::string& filepath, uint32_t stripe_h
|
|
|
467
461
|
ProcessResult *result = polygon_finder.process_info();
|
|
468
462
|
if (result) {
|
|
469
463
|
std::cout << "stripe " << stripe_count << ": found polygons " << result->groups << std::endl;
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
vmerger.add_tile(*safe_result, !(current_y_offset + stripe_height < total_height));
|
|
473
|
-
delete result;
|
|
464
|
+
result_clones.push_back(result);
|
|
465
|
+
vmerger.add_tile(*result, !(current_y_offset + stripe_height < total_height));
|
|
474
466
|
}
|
|
475
467
|
stripe_count++;
|
|
476
468
|
}
|
|
@@ -100,33 +100,31 @@ Node* Node::my_next_outer(Node *last, int versus) {
|
|
|
100
100
|
return get_tangent_node_by_virtual_index(this->tangs_sequence[last_node_index]);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
Point
|
|
103
|
+
Point Node::coords_entering_to(Node *enter_to, int mode, int tracking) {
|
|
104
104
|
int enter_to_index;
|
|
105
105
|
if (enter_to->y < this->y) enter_to_index = enter_to->abs_x_index + this->up_indexer;
|
|
106
106
|
else enter_to_index = this->down_indexer - enter_to->abs_x_index;
|
|
107
107
|
|
|
108
108
|
int tg_index = this->tangs_sequence[enter_to_index];
|
|
109
|
-
Point* point;
|
|
110
109
|
if (tg_index < 0) {
|
|
111
110
|
Node& node_up = cluster->vert_nodes[y + T_UP][-(tg_index + 1)];
|
|
112
111
|
if (mode == Node::A) {
|
|
113
112
|
enter_to->track |= TURNER[tracking][OMAX - 1];
|
|
114
|
-
|
|
113
|
+
return node_up.end_point;
|
|
115
114
|
} else {
|
|
116
115
|
enter_to->track |= TURNER[tracking][OMIN - 1];
|
|
117
|
-
|
|
116
|
+
return node_up.start_point;
|
|
118
117
|
}
|
|
119
118
|
} else {
|
|
120
119
|
Node& node_down = cluster->vert_nodes[y + T_DOWN][tg_index];
|
|
121
120
|
if (mode == Node::A) {
|
|
122
121
|
enter_to->track |= TURNER[tracking][OMIN - 1];
|
|
123
|
-
|
|
122
|
+
return node_down.start_point;
|
|
124
123
|
} else {
|
|
125
124
|
enter_to->track |= TURNER[tracking][OMAX - 1];
|
|
126
|
-
|
|
125
|
+
return node_down.end_point;
|
|
127
126
|
}
|
|
128
127
|
}
|
|
129
|
-
return point;
|
|
130
128
|
}
|
|
131
129
|
|
|
132
130
|
Node* Node::get_tangent_node_by_virtual_index(int virtual_index) {
|
|
@@ -61,6 +61,9 @@ struct Point {
|
|
|
61
61
|
bool operator==(const Point& other) const {
|
|
62
62
|
return x == other.x && y == other.y;
|
|
63
63
|
}
|
|
64
|
+
bool operator!=(const Point& other) const {
|
|
65
|
+
return !(*this == other);
|
|
66
|
+
}
|
|
64
67
|
Point(int x_, int y_) : x(x_), y(y_) {}
|
|
65
68
|
Point() : x(0), y(0) {}
|
|
66
69
|
};
|
|
@@ -96,7 +99,7 @@ class Node : public Listable {
|
|
|
96
99
|
NodeCluster* cluster;
|
|
97
100
|
void add_intersection(Node& other_node, int other_node_index);
|
|
98
101
|
SmallVec tangs_sequence;
|
|
99
|
-
Point
|
|
102
|
+
Point coords_entering_to(Node *enter_to, int mode, int tracking);
|
|
100
103
|
Node* my_next_outer(Node *last, int versus);
|
|
101
104
|
Node* my_next_inner(Node *last, int versus);
|
|
102
105
|
Node* get_tangent_node_by_virtual_index(int vitual_index);
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
#include "NodeCluster.h"
|
|
19
19
|
#include "Node.h"
|
|
20
20
|
#include "RectBounds.h"
|
|
21
|
-
#include "PointPool.h"
|
|
22
21
|
#include "../reducers/UniqReducer.h"
|
|
23
22
|
#include "../reducers/LinearReducer.h"
|
|
24
23
|
#include "../reducers/VisvalingamReducer.h"
|
|
@@ -44,7 +43,7 @@ NodeCluster::~NodeCluster() {
|
|
|
44
43
|
void NodeCluster::compress_coords(std::list<Polygon>& polygons, pf_Options options) {
|
|
45
44
|
if (!(options.compress_linear || options.compress_uniq || options.compress_visvalingam)) return;
|
|
46
45
|
|
|
47
|
-
auto compress_sequence = [&](std::vector<Point
|
|
46
|
+
auto compress_sequence = [&](std::vector<Point>& points_vec) {
|
|
48
47
|
if (points_vec.empty()) return;
|
|
49
48
|
|
|
50
49
|
if (options.compress_uniq) {
|
|
@@ -122,9 +121,9 @@ void NodeCluster::plot(int versus) {
|
|
|
122
121
|
next_node = root_node->get_tangent_node_by_virtual_index(root_node->tangs_sequence.front());
|
|
123
122
|
|
|
124
123
|
if (next_node != nullptr)
|
|
125
|
-
{ Point
|
|
124
|
+
{ Point p = next_node->coords_entering_to(root_node, versus_inverter[versus], Node::OUTER);
|
|
125
|
+
poly.bounds.expand(p.x, p.y);
|
|
126
126
|
poly.outer.push_back(p);
|
|
127
|
-
poly.bounds.expand(p->x, p->y);
|
|
128
127
|
}
|
|
129
128
|
if ((this->nodes > 0) && (next_node != nullptr))
|
|
130
129
|
{ plot_node(poly.outer, next_node, root_node, versus, poly.bounds);
|
|
@@ -137,7 +136,7 @@ void NodeCluster::plot(int versus) {
|
|
|
137
136
|
int index_inner = 0;
|
|
138
137
|
while (inner_plot->size() > 0)
|
|
139
138
|
{ this->plot_sequence.clear();
|
|
140
|
-
std::vector<Point
|
|
139
|
+
std::vector<Point> inner_sequence;
|
|
141
140
|
std::list<Node*>::iterator first_i;
|
|
142
141
|
Node *first = nullptr;
|
|
143
142
|
|
|
@@ -243,7 +242,7 @@ std::pair<int, int> NodeCluster::test_in_hole_o(Node* node)
|
|
|
243
242
|
return {-1, -1};
|
|
244
243
|
}
|
|
245
244
|
|
|
246
|
-
void NodeCluster::plot_inner_node(std::vector<Point
|
|
245
|
+
void NodeCluster::plot_inner_node(std::vector<Point>& sequence_coords, Node *node, int versus, Node *stop_at, Node *start_node) {
|
|
247
246
|
Node *current_node = node;
|
|
248
247
|
bool strict_bounds = this->options->strict_bounds;
|
|
249
248
|
while (current_node != nullptr) {
|
|
@@ -279,8 +278,8 @@ void NodeCluster::plot_inner_node(std::vector<Point*>& sequence_coords, Node *no
|
|
|
279
278
|
}
|
|
280
279
|
}
|
|
281
280
|
} else if (strict_bounds) {
|
|
282
|
-
sequence_coords.push_back(
|
|
283
|
-
sequence_coords.push_back(
|
|
281
|
+
sequence_coords.push_back(Point{(first_is_max ? last_node->max_x : last_node->min_x), current_node->y});
|
|
282
|
+
sequence_coords.push_back(Point{(first_is_max ? next_node->min_x : next_node->max_x), current_node->y});
|
|
284
283
|
}
|
|
285
284
|
|
|
286
285
|
if (current_node->track_uncomplete()) {
|
|
@@ -293,7 +292,7 @@ void NodeCluster::plot_inner_node(std::vector<Point*>& sequence_coords, Node *no
|
|
|
293
292
|
}
|
|
294
293
|
}
|
|
295
294
|
|
|
296
|
-
void NodeCluster::plot_node(std::vector<Point
|
|
295
|
+
void NodeCluster::plot_node(std::vector<Point>& sequence_coords, Node *node, Node *start_node, int versus, RectBounds& bounds) {
|
|
297
296
|
Node *current_node = node;
|
|
298
297
|
bool strict_bounds = this->options->strict_bounds;
|
|
299
298
|
|
|
@@ -315,23 +314,23 @@ void NodeCluster::plot_node(std::vector<Point*>& sequence_coords, Node *node, No
|
|
|
315
314
|
plot = (n == next_node);
|
|
316
315
|
}
|
|
317
316
|
if (plot) {
|
|
318
|
-
Point
|
|
317
|
+
Point p = last_node->coords_entering_to(current_node, versus, Node::OUTER);
|
|
318
|
+
bounds.expand(p.x, p.y);
|
|
319
319
|
sequence_coords.push_back(p);
|
|
320
|
-
bounds.expand(p->x, p->y);
|
|
321
320
|
if (current_node != start_node) {
|
|
322
321
|
inner_plot->contains(current_node) ? inner_plot->remove(current_node) : inner_plot->push_back(current_node);
|
|
323
322
|
if (last_node->y == next_node->y) {
|
|
324
|
-
Point
|
|
323
|
+
Point p1 = next_node->coords_entering_to(current_node, versus_inverter[versus], Node::OUTER);
|
|
324
|
+
bounds.expand(p1.x, p1.y);
|
|
325
325
|
sequence_coords.push_back(p1);
|
|
326
|
-
bounds.expand(p1->x, p1->y);
|
|
327
326
|
inner_plot->contains(current_node) ? inner_plot->remove(current_node) : inner_plot->push_back(current_node);
|
|
328
327
|
}
|
|
329
328
|
}
|
|
330
329
|
} else if (strict_bounds) {
|
|
331
330
|
bool is_down = current_node->y > last_node->y;
|
|
332
331
|
bool is_a = (versus == Node::A);
|
|
333
|
-
sequence_coords.push_back(
|
|
334
|
-
sequence_coords.push_back(
|
|
332
|
+
sequence_coords.push_back(Point{(is_down == is_a ? last_node->min_x : last_node->max_x), current_node->y});
|
|
333
|
+
sequence_coords.push_back(Point{(is_down == is_a ? next_node->max_x : next_node->min_x), current_node->y});
|
|
335
334
|
}
|
|
336
335
|
|
|
337
336
|
if (current_node == start_node) {
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
#include "Lists.h"
|
|
19
19
|
#include "RectBounds.h"
|
|
20
20
|
#include "Polygon.h"
|
|
21
|
-
#include "PointPool.h"
|
|
22
21
|
|
|
23
22
|
class Node;
|
|
24
23
|
struct Point;
|
|
@@ -26,8 +25,8 @@ struct pf_Options;
|
|
|
26
25
|
|
|
27
26
|
class NodeCluster {
|
|
28
27
|
private:
|
|
29
|
-
void plot_node(std::vector<Point
|
|
30
|
-
void plot_inner_node(std::vector<Point
|
|
28
|
+
void plot_node(std::vector<Point>& sequence_coords, Node *node, Node *start_node, int versus, RectBounds& bounds);
|
|
29
|
+
void plot_inner_node(std::vector<Point>& sequence_coords, Node *node, int versus, Node *stop_at, Node *start_node);
|
|
31
30
|
std::vector<Node*> plot_sequence;
|
|
32
31
|
List *inner_plot;
|
|
33
32
|
List *inner_new;
|
|
@@ -35,7 +34,6 @@ class NodeCluster {
|
|
|
35
34
|
int count = 0;
|
|
36
35
|
int nodes;
|
|
37
36
|
int width;
|
|
38
|
-
PointPool points_pool;
|
|
39
37
|
|
|
40
38
|
public:
|
|
41
39
|
pf_Options *options;
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
#include "RectBounds.h"
|
|
15
15
|
|
|
16
16
|
struct Polygon {
|
|
17
|
-
std::vector<Point
|
|
18
|
-
std::list<std::vector<Point
|
|
17
|
+
std::vector<Point> outer;
|
|
18
|
+
std::list<std::vector<Point>> inner;
|
|
19
19
|
RectBounds bounds;
|
|
20
20
|
Polygon() : bounds(RectBounds::empty()) {}
|
|
21
21
|
};
|
|
@@ -108,6 +108,7 @@ ProcessResult* PolygonFinder::process_info() {
|
|
|
108
108
|
pr->width = this->source_bitmap->w();
|
|
109
109
|
pr->height = this->source_bitmap->h();
|
|
110
110
|
pr->has_bounds = this->node_cluster->options->bounds;
|
|
111
|
+
pr->versus = this->options.versus;
|
|
111
112
|
|
|
112
113
|
if (this->node_cluster->options->named_sequences && typeid(*this->source_bitmap) == typeid(Bitmap))
|
|
113
114
|
{ std::string sequence;
|
|
@@ -133,25 +134,25 @@ void ProcessResult::draw_on_bitmap(RawBitmap& bitmap) const {
|
|
|
133
134
|
// --- OUTER ---
|
|
134
135
|
if (!poly.outer.empty()) {
|
|
135
136
|
for (size_t i = 0; i < poly.outer.size() - 1; ++i) {
|
|
136
|
-
Point
|
|
137
|
-
Point
|
|
138
|
-
bitmap.draw_line(p1
|
|
137
|
+
const Point& p1 = poly.outer[i];
|
|
138
|
+
const Point& p2 = poly.outer[i+1];
|
|
139
|
+
bitmap.draw_line(p1.x, p1.y, p2.x, p2.y, 255, 0, 0, 255);
|
|
139
140
|
}
|
|
140
|
-
Point
|
|
141
|
-
Point
|
|
142
|
-
bitmap.draw_line(last
|
|
141
|
+
const Point& last = poly.outer.back();
|
|
142
|
+
const Point& first = poly.outer.front();
|
|
143
|
+
bitmap.draw_line(last.x, last.y, first.x, first.y, 255, 0, 0, 255);
|
|
143
144
|
}
|
|
144
145
|
// --- INNER ---
|
|
145
146
|
for (const auto& sequence : poly.inner) {
|
|
146
147
|
if (sequence.empty()) continue;
|
|
147
148
|
for (size_t i = 0; i < sequence.size() - 1; ++i) {
|
|
148
|
-
Point
|
|
149
|
-
Point
|
|
150
|
-
bitmap.draw_line(p1
|
|
149
|
+
const Point& p1 = sequence[i];
|
|
150
|
+
const Point& p2 = sequence[i+1];
|
|
151
|
+
bitmap.draw_line(p1.x, p1.y, p2.x, p2.y, 0, 128, 0, 255);
|
|
151
152
|
}
|
|
152
|
-
Point
|
|
153
|
-
Point
|
|
154
|
-
bitmap.draw_line(last
|
|
153
|
+
const Point& last = sequence.back();
|
|
154
|
+
const Point& first = sequence.front();
|
|
155
|
+
bitmap.draw_line(last.x, last.y, first.x, first.y, 0, 128, 0, 255);
|
|
155
156
|
}
|
|
156
157
|
}
|
|
157
158
|
}
|
|
@@ -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
|
}
|
|
@@ -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
|
};
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
#include <vector>
|
|
12
12
|
#include "InnerPolyline.h"
|
|
13
13
|
|
|
14
|
-
InnerPolyline::InnerPolyline(std::vector<Point
|
|
14
|
+
InnerPolyline::InnerPolyline(std::vector<Point> raw_coordinates, Shape* shape)
|
|
15
15
|
: raw_coordinates_(std::move(raw_coordinates)),
|
|
16
16
|
shape_(shape) {}
|
|
17
17
|
InnerPolyline::InnerPolyline(Sequence* sequence)
|
|
@@ -19,7 +19,7 @@ InnerPolyline::InnerPolyline(Sequence* sequence)
|
|
|
19
19
|
this->raw_coordinates_ = sequence->to_vector();
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
std::vector<Point
|
|
22
|
+
std::vector<Point>& InnerPolyline::raw() {
|
|
23
23
|
return this->raw_coordinates_;
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -41,11 +41,11 @@ Shape* InnerPolyline::shape() {
|
|
|
41
41
|
|
|
42
42
|
Bounds& InnerPolyline::raw_vertical_bounds() {
|
|
43
43
|
if (!raw_coordinates_.empty()) {
|
|
44
|
-
int min_y = raw_coordinates_[0]
|
|
45
|
-
int max_y = raw_coordinates_[0]
|
|
44
|
+
int min_y = raw_coordinates_[0].y;
|
|
45
|
+
int max_y = raw_coordinates_[0].y;
|
|
46
46
|
for (const auto& pos : raw_coordinates_) {
|
|
47
|
-
if (pos
|
|
48
|
-
if (pos
|
|
47
|
+
if (pos.y < min_y) min_y = pos.y;
|
|
48
|
+
if (pos.y > max_y) max_y = pos.y;
|
|
49
49
|
}
|
|
50
50
|
vertical_bounds_.min = min_y;
|
|
51
51
|
vertical_bounds_.max = max_y;
|
|
@@ -14,15 +14,15 @@
|
|
|
14
14
|
|
|
15
15
|
class InnerPolyline {
|
|
16
16
|
public:
|
|
17
|
-
explicit InnerPolyline(std::vector<Point
|
|
17
|
+
explicit InnerPolyline(std::vector<Point> raw_coordinates, Shape* shape);
|
|
18
18
|
explicit InnerPolyline(Sequence* sequence);
|
|
19
|
-
std::vector<Point
|
|
19
|
+
std::vector<Point>& raw();
|
|
20
20
|
Sequence* sequence() { return this->sequence_; }
|
|
21
21
|
Bounds& vertical_bounds();
|
|
22
22
|
Shape* shape();
|
|
23
23
|
Shape* assigned_shape = nullptr;
|
|
24
24
|
private:
|
|
25
|
-
std::vector<Point
|
|
25
|
+
std::vector<Point> raw_coordinates_;
|
|
26
26
|
Sequence* sequence_ = nullptr;
|
|
27
27
|
Shape* shape_;
|
|
28
28
|
Bounds& raw_vertical_bounds();
|