contrek 1.2.0 → 1.2.2
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/CHANGELOG.md +9 -1
- data/Gemfile.lock +1 -1
- data/PERFORMANCE.md +177 -0
- data/README.md +22 -3
- data/Rakefile +1 -1
- data/contrek.gemspec +5 -1
- data/ext/cpp_polygon_finder/PolygonFinder/CMakeLists.txt +10 -12
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.cpp +2 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.h +36 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.cpp +4 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.cpp +33 -42
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.h +2 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.cpp +33 -5
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.h +3 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Hub.cpp +2 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Hub.h +1 -5
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/InnerPolyline.cpp +1 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/InnerPolyline.h +1 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +16 -20
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +8 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.cpp +5 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.h +3 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ShapePool.cpp +2 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ShapePool.h +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.cpp +5 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.h +4 -4
- data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +9 -0
- data/lib/contrek/finder/concurrent/cluster.rb +30 -29
- data/lib/contrek/finder/concurrent/cursor.rb +35 -12
- data/lib/contrek/finder/concurrent/hub.rb +1 -1
- data/lib/contrek/finder/concurrent/inner_polyline.rb +2 -3
- data/lib/contrek/finder/concurrent/polyline.rb +5 -7
- data/lib/contrek/finder/concurrent/shape.rb +7 -3
- data/lib/contrek/finder/concurrent/tile.rb +5 -4
- data/lib/contrek/version.rb +1 -1
- metadata +3 -6
- data/ext/cpp_polygon_finder/PolygonFinder/examples/example.cpp +0 -50
- data/ext/cpp_polygon_finder/PolygonFinder/images/graphs_1024x1024.png +0 -0
- data/ext/cpp_polygon_finder/PolygonFinder/images/labyrinth.png +0 -0
- data/ext/cpp_polygon_finder/PolygonFinder/images/sample_10240x10240.png +0 -0
|
@@ -129,7 +129,7 @@ void Cursor::traverse_outer(Part* act_part,
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
std::vector<InnerPolyline*> Cursor::join_inners(Sequence* outer_seq) {
|
|
132
|
+
std::vector<InnerPolyline*> Cursor::join_inners(Sequence* outer_seq, bool treemap) {
|
|
133
133
|
std::vector<InnerPolyline*> return_inner_polylines;
|
|
134
134
|
std::vector<Shape*> processing_queue = shapes_sequence_;
|
|
135
135
|
for (size_t i = 0; i < shapes_sequence_.size(); ++i)
|
|
@@ -138,11 +138,12 @@ std::vector<InnerPolyline*> Cursor::join_inners(Sequence* outer_seq) {
|
|
|
138
138
|
for (Part* part : polyline->parts())
|
|
139
139
|
{ if (part->innerable())
|
|
140
140
|
{ std::vector<Part*> all_parts;
|
|
141
|
+
std::vector<EndPoint*> tracked_end_points;
|
|
141
142
|
Bounds bounds{
|
|
142
143
|
.min = polyline->max_y(),
|
|
143
144
|
.max = 0
|
|
144
145
|
};
|
|
145
|
-
traverse_inner(part, all_parts, bounds);
|
|
146
|
+
traverse_inner(part, all_parts, bounds, tracked_end_points);
|
|
146
147
|
Sequence* retme_sequence = shape->outer_polyline->tile->shapes_pool->acquire_sequence();
|
|
147
148
|
for (Part* part : all_parts)
|
|
148
149
|
{ part->touch();
|
|
@@ -157,7 +158,11 @@ std::vector<InnerPolyline*> Cursor::join_inners(Sequence* outer_seq) {
|
|
|
157
158
|
});
|
|
158
159
|
}
|
|
159
160
|
if (retme_sequence->is_not_vertical()) {
|
|
160
|
-
|
|
161
|
+
InnerPolyline* inner_polyline = polyline->tile->shapes_pool->acquire_inner_polyline(retme_sequence);
|
|
162
|
+
return_inner_polylines.push_back(inner_polyline);
|
|
163
|
+
if (treemap) {
|
|
164
|
+
mark_children(tracked_end_points, polyline, inner_polyline);
|
|
165
|
+
}
|
|
161
166
|
}
|
|
162
167
|
}
|
|
163
168
|
}
|
|
@@ -165,7 +170,26 @@ std::vector<InnerPolyline*> Cursor::join_inners(Sequence* outer_seq) {
|
|
|
165
170
|
return(return_inner_polylines);
|
|
166
171
|
}
|
|
167
172
|
|
|
168
|
-
void Cursor::
|
|
173
|
+
void Cursor::mark_children(std::vector<EndPoint*>& end_points, const Polyline* outer_polyline, InnerPolyline* inner_polyline) {
|
|
174
|
+
for (size_t i = 0; i + 1 < end_points.size(); i += 2) {
|
|
175
|
+
const auto& a = end_points[i];
|
|
176
|
+
const auto& b = end_points[i + 1];
|
|
177
|
+
auto [y_min, y_max] = std::minmax(a->get_point()->y, b->get_point()->y);
|
|
178
|
+
for (int y = y_min + 1; y < y_max; ++y) {
|
|
179
|
+
EndPoint* end_point = this->cluster.hub()->get(y);
|
|
180
|
+
if (end_point) {
|
|
181
|
+
for (auto part_p : end_point->queues())
|
|
182
|
+
{ Part* part = static_cast<Part*>(part_p);
|
|
183
|
+
if (part->polyline() != outer_polyline) {
|
|
184
|
+
part->polyline()->inside_inner_polyline = inner_polyline;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
void Cursor::traverse_inner(Part* act_part, std::vector<Part*>& all_parts, Bounds& bounds, std::vector<EndPoint*>& tracked_end_points) {
|
|
169
193
|
PartPool& pool = act_part->polyline()->tile->cluster->parts_pool;
|
|
170
194
|
while (act_part != nullptr) {
|
|
171
195
|
if (!all_parts.empty() && act_part == all_parts.front()) return;
|
|
@@ -186,13 +210,17 @@ void Cursor::traverse_inner(Part* act_part, std::vector<Part*>& all_parts, Bound
|
|
|
186
210
|
all_parts.push_back(act_part);
|
|
187
211
|
} else {
|
|
188
212
|
if (act_part->head)
|
|
189
|
-
{
|
|
213
|
+
{ EndPoint* current_end_point = static_cast<Position*>(act_part->head)->end_point();
|
|
214
|
+
for (auto dest_part_p : current_end_point->queues()) {
|
|
190
215
|
Part* dest_part = static_cast<Part*>(dest_part_p);
|
|
191
216
|
if (dest_part->polyline()->tile == act_part->polyline()->tile) {
|
|
192
217
|
continue;
|
|
193
218
|
}
|
|
194
219
|
int dest_part_versus = dest_part->versus();
|
|
195
220
|
if (dest_part_versus != 0 && dest_part_versus == act_part->versus()) continue;
|
|
221
|
+
|
|
222
|
+
tracked_end_points.push_back(current_end_point);
|
|
223
|
+
|
|
196
224
|
std::vector<EndPoint*> link_seq = dest_part->continuum_to(*act_part);
|
|
197
225
|
if (!link_seq.empty()) {
|
|
198
226
|
Part* ins_part = pool.acquire(Part::ADDED, act_part->polyline());
|
|
@@ -21,7 +21,7 @@ class Cursor {
|
|
|
21
21
|
public:
|
|
22
22
|
Cursor(Cluster& cluster, Shape* shape);
|
|
23
23
|
Sequence* join_outers();
|
|
24
|
-
std::vector<InnerPolyline*> join_inners(Sequence* outer_seq);
|
|
24
|
+
std::vector<InnerPolyline*> join_inners(Sequence* outer_seq, bool treemap);
|
|
25
25
|
std::list<InnerPolyline*> orphan_inners() { return orphan_inners_; }
|
|
26
26
|
const std::vector<Shape*>& shapes_sequence() const { return shapes_sequence_; }
|
|
27
27
|
|
|
@@ -35,6 +35,7 @@ class Cursor {
|
|
|
35
35
|
std::vector<Part*>& all_parts,
|
|
36
36
|
std::vector<Shape*>& shapes_sequence,
|
|
37
37
|
Sequence* outer_joined_polyline);
|
|
38
|
-
void traverse_inner(Part* act_part, std::vector<Part*> &all_parts, Bounds& bounds);
|
|
38
|
+
void traverse_inner(Part* act_part, std::vector<Part*> &all_parts, Bounds& bounds, std::vector<EndPoint*>& tracked_end_points);
|
|
39
39
|
std::vector<Shape*> connect_missings(std::vector<Shape*> shapes_sequence, std::vector<Shape*> missing_shapes);
|
|
40
|
+
void mark_children(std::vector<EndPoint*>& end_points, const Polyline* outer_polyline, InnerPolyline* inner_polyline);
|
|
40
41
|
};
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
#include "Hub.h"
|
|
11
11
|
#include <cstring>
|
|
12
12
|
|
|
13
|
-
Hub::Hub(int height
|
|
14
|
-
:
|
|
13
|
+
Hub::Hub(int height)
|
|
14
|
+
: height_(height)
|
|
15
15
|
{ size_t total_pixels = static_cast<size_t>(height);
|
|
16
16
|
payloads_.resize(total_pixels);
|
|
17
17
|
bitset_.resize((total_pixels + 63) / 64, 0);
|
|
@@ -15,10 +15,8 @@
|
|
|
15
15
|
class EndPoint;
|
|
16
16
|
class Hub {
|
|
17
17
|
public:
|
|
18
|
-
explicit Hub(int height
|
|
18
|
+
explicit Hub(int height);
|
|
19
19
|
int spawn_end_point();
|
|
20
|
-
const int width() const { return width_; }
|
|
21
|
-
const int start_x() const { return start_x_; }
|
|
22
20
|
inline EndPoint* get(int key) {
|
|
23
21
|
if (!is_set(key)) return nullptr;
|
|
24
22
|
int index = payloads_[key];
|
|
@@ -34,9 +32,7 @@ class Hub {
|
|
|
34
32
|
}
|
|
35
33
|
|
|
36
34
|
private:
|
|
37
|
-
int width_;
|
|
38
35
|
int height_;
|
|
39
|
-
int start_x_;
|
|
40
36
|
std::vector<int> payloads_;
|
|
41
37
|
std::vector<EndPoint> endpoint_pool_;
|
|
42
38
|
Hub(const Hub&) = delete;
|
|
@@ -11,9 +11,8 @@
|
|
|
11
11
|
#include <vector>
|
|
12
12
|
#include "InnerPolyline.h"
|
|
13
13
|
|
|
14
|
-
InnerPolyline::InnerPolyline(std::vector<Point*> raw_coordinates, Shape* shape
|
|
14
|
+
InnerPolyline::InnerPolyline(std::vector<Point*> raw_coordinates, Shape* shape)
|
|
15
15
|
: raw_coordinates_(std::move(raw_coordinates)),
|
|
16
|
-
recombined_(recombined),
|
|
17
16
|
shape_(shape) {}
|
|
18
17
|
InnerPolyline::InnerPolyline(Sequence* sequence)
|
|
19
18
|
: sequence_(sequence) {
|
|
@@ -14,16 +14,14 @@
|
|
|
14
14
|
|
|
15
15
|
class InnerPolyline {
|
|
16
16
|
public:
|
|
17
|
-
explicit InnerPolyline(std::vector<Point*> raw_coordinates, Shape* shape
|
|
17
|
+
explicit InnerPolyline(std::vector<Point*> raw_coordinates, Shape* shape);
|
|
18
18
|
explicit InnerPolyline(Sequence* sequence);
|
|
19
19
|
std::vector<Point*>& raw();
|
|
20
20
|
Sequence* sequence() { return this->sequence_; }
|
|
21
21
|
Bounds& vertical_bounds();
|
|
22
|
-
bool recombined() { return this->recombined_; }
|
|
23
22
|
Shape* shape();
|
|
24
23
|
Shape* assigned_shape = nullptr;
|
|
25
24
|
private:
|
|
26
|
-
bool recombined_ = false;
|
|
27
25
|
std::vector<Point*> raw_coordinates_;
|
|
28
26
|
Sequence* sequence_ = nullptr;
|
|
29
27
|
Shape* shape_;
|
|
@@ -22,15 +22,12 @@ Polyline::Polyline(Tile* tile, const std::vector<Point*>& polygon, const std::op
|
|
|
22
22
|
{ if (bounds.has_value()) {
|
|
23
23
|
min_x = bounds->min_x;
|
|
24
24
|
max_x = bounds->max_x;
|
|
25
|
-
|
|
25
|
+
min_y_ = bounds->min_y;
|
|
26
26
|
max_y_ = bounds->max_y;
|
|
27
27
|
} else {
|
|
28
28
|
this->find_boundary(); // TODO(ema): optimize when merging the bounds are the sum of the previouses
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
bool Polyline::vert_intersect(Polyline& other) {
|
|
33
|
-
return( !(this->max_y_ < other.min_y || other.max_y_ < this->min_y));
|
|
30
|
+
this->name = tile->shapes().size();
|
|
34
31
|
}
|
|
35
32
|
|
|
36
33
|
int Polyline::width() {
|
|
@@ -46,7 +43,7 @@ void Polyline::find_boundary() {
|
|
|
46
43
|
if (raw_.empty()) return;
|
|
47
44
|
min_x = std::numeric_limits<int>::max();
|
|
48
45
|
max_x = -std::numeric_limits<int>::max();
|
|
49
|
-
|
|
46
|
+
min_y_ = std::numeric_limits<int>::max();
|
|
50
47
|
max_y_ = -std::numeric_limits<int>::max();
|
|
51
48
|
for (Point* p : raw_) {
|
|
52
49
|
if (!p) continue;
|
|
@@ -54,7 +51,7 @@ void Polyline::find_boundary() {
|
|
|
54
51
|
int y = p->y;
|
|
55
52
|
if (x < min_x) min_x = x;
|
|
56
53
|
if (x > max_x) max_x = x;
|
|
57
|
-
if (y <
|
|
54
|
+
if (y < min_y_) min_y_ = y;
|
|
58
55
|
if (y > max_y_) max_y_ = y;
|
|
59
56
|
}
|
|
60
57
|
}
|
|
@@ -67,20 +64,8 @@ bool Polyline::is_empty() {
|
|
|
67
64
|
return raw_.empty();
|
|
68
65
|
}
|
|
69
66
|
|
|
70
|
-
std::string Polyline::info() {
|
|
71
|
-
Shape* shape = this->shape;
|
|
72
|
-
size_t part_index = 0;
|
|
73
|
-
auto it = std::find(this->tile->shapes().begin(), this->tile->shapes().end(), shape);
|
|
74
|
-
if (it != this->tile->shapes().end()) {
|
|
75
|
-
part_index = std::distance(this->tile->shapes().begin(), it);
|
|
76
|
-
}
|
|
77
|
-
std::stringstream ss;
|
|
78
|
-
ss << "b" << this->tile->name() << " S" << part_index;
|
|
79
|
-
return ss.str();
|
|
80
|
-
}
|
|
81
|
-
|
|
82
67
|
bool Polyline::vert_bounds_intersect(Bounds& vertical_bounds)
|
|
83
|
-
{ return !(this->max_y_ < vertical_bounds.min || vertical_bounds.max < this->
|
|
68
|
+
{ return !(this->max_y_ < vertical_bounds.min || vertical_bounds.max < this->min_y_);
|
|
84
69
|
}
|
|
85
70
|
|
|
86
71
|
bool Polyline::within(std::vector<Point*>& points) {
|
|
@@ -99,3 +84,14 @@ bool Polyline::within(std::vector<Point*>& points) {
|
|
|
99
84
|
}
|
|
100
85
|
return inside;
|
|
101
86
|
}
|
|
87
|
+
|
|
88
|
+
std::string Polyline::named() {
|
|
89
|
+
if (this->named_.empty()) {
|
|
90
|
+
std::stringstream ss;
|
|
91
|
+
ss << "t" << this->tile->name() << "s" << this->name;
|
|
92
|
+
if (this->boundary()) ss << "B";
|
|
93
|
+
return ss.str();
|
|
94
|
+
} else {
|
|
95
|
+
return this->named_;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
class Tile;
|
|
24
24
|
class Shape;
|
|
25
25
|
class Point;
|
|
26
|
+
class InnerPolyline;
|
|
26
27
|
|
|
27
28
|
class Polyline : public Partitionable {
|
|
28
29
|
public:
|
|
@@ -42,17 +43,21 @@ class Polyline : public Partitionable {
|
|
|
42
43
|
std::vector<Point*> raw() const { return raw_; }
|
|
43
44
|
const std::vector<Part*>& parts() const { return parts_; }
|
|
44
45
|
const int max_y() const { return max_y_; }
|
|
46
|
+
const int min_y() const { return min_y_; }
|
|
45
47
|
void clear();
|
|
46
48
|
bool is_empty();
|
|
47
|
-
bool vert_intersect(Polyline& other);
|
|
48
49
|
bool any_ancients = false;
|
|
49
|
-
std::string info();
|
|
50
50
|
bool vert_bounds_intersect(Bounds& vertical_bounds);
|
|
51
51
|
bool within(std::vector<Point*>& points);
|
|
52
|
+
InnerPolyline* inside_inner_polyline = nullptr;
|
|
53
|
+
std::string named();
|
|
54
|
+
void set_named(std::string force_named) { this->named_ = force_named; }
|
|
52
55
|
|
|
53
56
|
private:
|
|
54
57
|
std::vector<Point*> raw_;
|
|
55
|
-
int min_x, max_x,
|
|
58
|
+
int min_x, max_x, min_y_, max_y_;
|
|
56
59
|
void find_boundary();
|
|
57
60
|
uint32_t flags_ = 0;
|
|
61
|
+
std::string named_;
|
|
62
|
+
int name;
|
|
58
63
|
};
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
#include <list>
|
|
11
11
|
#include <vector>
|
|
12
|
+
#include <string>
|
|
12
13
|
#include "Shape.h"
|
|
13
14
|
#include "Polyline.h"
|
|
14
15
|
|
|
@@ -34,3 +35,7 @@ void Shape::set_parent_shape(Shape* shape) {
|
|
|
34
35
|
{ shape->children_shapes.push_back(this);
|
|
35
36
|
}
|
|
36
37
|
}
|
|
38
|
+
|
|
39
|
+
std::string Shape::name() {
|
|
40
|
+
return(this->outer_polyline->named());
|
|
41
|
+
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
#include <list>
|
|
12
12
|
#include <iostream>
|
|
13
13
|
#include <vector>
|
|
14
|
+
#include <string>
|
|
14
15
|
#include "InnerPolyline.h"
|
|
15
16
|
|
|
16
17
|
class Point;
|
|
@@ -24,9 +25,10 @@ class Shape {
|
|
|
24
25
|
InnerPolyline* parent_inner_polyline = nullptr;
|
|
25
26
|
std::vector<Shape*> children_shapes;
|
|
26
27
|
void clear_inner();
|
|
27
|
-
bool
|
|
28
|
+
bool fixed = false;
|
|
28
29
|
Shape* parent_shape() { return parent_shape_; }
|
|
29
30
|
void set_parent_shape(Shape*);
|
|
31
|
+
std::string name();
|
|
30
32
|
private:
|
|
31
33
|
Shape* parent_shape_ = nullptr;
|
|
32
34
|
};
|
|
@@ -17,8 +17,8 @@ Shape* ShapePool::acquire_shape(Polyline* outer_polyline, const std::vector<Inne
|
|
|
17
17
|
return shape;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
InnerPolyline* ShapePool::acquire_inner_polyline(std::vector<Point*> coords, Shape* shape
|
|
21
|
-
inner_polylines_storage.emplace_back(coords, shape
|
|
20
|
+
InnerPolyline* ShapePool::acquire_inner_polyline(std::vector<Point*> coords, Shape* shape) {
|
|
21
|
+
inner_polylines_storage.emplace_back(coords, shape);
|
|
22
22
|
InnerPolyline* ip = &inner_polylines_storage.back();
|
|
23
23
|
return ip;
|
|
24
24
|
}
|
|
@@ -27,7 +27,7 @@ class ShapePool {
|
|
|
27
27
|
|
|
28
28
|
public:
|
|
29
29
|
Shape* acquire_shape(Polyline* outer_polyline, const std::vector<InnerPolyline*>& inner_polylines);
|
|
30
|
-
InnerPolyline* acquire_inner_polyline(std::vector<Point*> coords, Shape* s
|
|
30
|
+
InnerPolyline* acquire_inner_polyline(std::vector<Point*> coords, Shape* s);
|
|
31
31
|
InnerPolyline* acquire_inner_polyline(Sequence* seq);
|
|
32
32
|
Sequence* acquire_sequence();
|
|
33
33
|
Polyline* acquire_polyline(Tile* tile, const std::vector<Point*>& polygon, const std::optional<RectBounds>& bounds);
|
|
@@ -61,7 +61,7 @@ void Tile::assign_raw_polygons(const std::list<Polygon>& raw_polylines, const st
|
|
|
61
61
|
{ Polyline* polyline = this->shapes_pool->acquire_polyline(this, raw_polyline.outer, raw_polyline.bounds);
|
|
62
62
|
std::vector<InnerPolyline*> inner_polylines_list;
|
|
63
63
|
for (auto& raw_points : raw_polyline.inner) {
|
|
64
|
-
inner_polylines_list.push_back(this->shapes_pool->acquire_inner_polyline(raw_points, nullptr
|
|
64
|
+
inner_polylines_list.push_back(this->shapes_pool->acquire_inner_polyline(raw_points, nullptr));
|
|
65
65
|
}
|
|
66
66
|
Shape* shape = this->shapes_pool->acquire_shape(polyline, inner_polylines_list);
|
|
67
67
|
polyline->shape = shape;
|
|
@@ -75,6 +75,7 @@ void Tile::assign_raw_polygons(const std::list<Polygon>& raw_polylines, const st
|
|
|
75
75
|
if (it != shapes_map.end()) {
|
|
76
76
|
Shape* parent = it->second;
|
|
77
77
|
shape->set_parent_shape(parent);
|
|
78
|
+
shape->fixed = true;
|
|
78
79
|
shape->parent_inner_polyline = parent->inner_polylines[treemap_entry.second];
|
|
79
80
|
}
|
|
80
81
|
}
|
|
@@ -84,7 +85,7 @@ void Tile::assign_raw_polygons(const std::list<Polygon>& raw_polylines, const st
|
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
void Tile::assign_shapes(std::
|
|
88
|
+
void Tile::assign_shapes(std::vector<Shape*>& shapes) {
|
|
88
89
|
for (Shape *shape : shapes) {
|
|
89
90
|
shape->outer_polyline->tile = this;
|
|
90
91
|
}
|
|
@@ -135,7 +136,8 @@ std::vector<std::pair<int, int>> Tile::compute_treemap()
|
|
|
135
136
|
for (auto* shape : this->shapes_) {
|
|
136
137
|
if (shape->outer_polyline->is_empty()) continue;
|
|
137
138
|
if (shape->parent_shape() != nullptr) {
|
|
138
|
-
|
|
139
|
+
auto p_it = shapes_map.find(shape->parent_shape());
|
|
140
|
+
int p_idx = (p_it != shapes_map.end()) ? p_it->second : -1;
|
|
139
141
|
const auto& inners = shape->parent_shape()->inner_polylines;
|
|
140
142
|
auto it = std::find(inners.begin(), inners.end(), shape->parent_inner_polyline);
|
|
141
143
|
int inner_idx = static_cast<int>(std::distance(inners.begin(), it));
|
|
@@ -30,7 +30,7 @@ class Tile {
|
|
|
30
30
|
int start_x_;
|
|
31
31
|
int end_x_;
|
|
32
32
|
std::string name_;
|
|
33
|
-
std::
|
|
33
|
+
std::vector<Shape*> shapes_;
|
|
34
34
|
|
|
35
35
|
public:
|
|
36
36
|
Tile(Finder *finder, int start_x, int end_x, std::string name, const Benchmarks& b);
|
|
@@ -42,15 +42,15 @@ class Tile {
|
|
|
42
42
|
int start_x() const { return start_x_; }
|
|
43
43
|
int end_x() const { return end_x_; }
|
|
44
44
|
std::string name() const { return name_; }
|
|
45
|
-
const std::
|
|
46
|
-
std::
|
|
45
|
+
const std::vector<Shape*>& shapes() const { return shapes_; }
|
|
46
|
+
std::vector<Shape*>& shapes() { return shapes_; }
|
|
47
47
|
bool whole();
|
|
48
48
|
bool left();
|
|
49
49
|
bool right();
|
|
50
50
|
void initial_process(ClippedPolygonFinder *finder);
|
|
51
51
|
void info();
|
|
52
52
|
bool tg_border(const Point& coord);
|
|
53
|
-
void assign_shapes(std::
|
|
53
|
+
void assign_shapes(std::vector<Shape*>& shapes);
|
|
54
54
|
void assign_raw_polygons(const std::list<Polygon>& raw_polylines, const std::vector<std::pair<int, int>>& treemap);
|
|
55
55
|
std::list<Polygon> to_raw_polygons();
|
|
56
56
|
std::vector<std::pair<int, int>> compute_treemap();
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
* Copyright 2025 Emanuele Cesaroni
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
#ifdef HAVE_TCMALLOC
|
|
10
|
+
#include <gperftools/malloc_extension.h>
|
|
11
|
+
#endif
|
|
9
12
|
#include <iostream>
|
|
10
13
|
#include <list>
|
|
11
14
|
#include <vector>
|
|
@@ -286,6 +289,12 @@ ProcessResult ruby_result_to_process_result(Rice::Object rb_result) {
|
|
|
286
289
|
|
|
287
290
|
extern "C"
|
|
288
291
|
void Init_cpp_polygon_finder() {
|
|
292
|
+
#ifdef HAVE_TCMALLOC
|
|
293
|
+
MallocExtension::instance()->SetNumericProperty(
|
|
294
|
+
"tcmalloc.max_total_thread_cache_bytes",
|
|
295
|
+
1024 * 1024 * 1024);
|
|
296
|
+
#endif
|
|
297
|
+
|
|
289
298
|
Data_Type<Bitmap> rb_cBitmap =
|
|
290
299
|
define_class<Bitmap>("CPPBitMap")
|
|
291
300
|
.define_constructor(Constructor<Bitmap, std::string, int>())
|
|
@@ -6,7 +6,7 @@ module Contrek
|
|
|
6
6
|
def initialize(finder:, height:, start_x:, end_x:)
|
|
7
7
|
@finder = finder
|
|
8
8
|
@tiles = []
|
|
9
|
-
@hub = Hub.new(height
|
|
9
|
+
@hub = Hub.new(height:)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def add(tile)
|
|
@@ -28,6 +28,7 @@ module Contrek
|
|
|
28
28
|
|
|
29
29
|
new_shapes = []
|
|
30
30
|
all_new_inner_polylines = []
|
|
31
|
+
|
|
31
32
|
tot_outer += Benchmark.measure do
|
|
32
33
|
@tiles.each do |tile|
|
|
33
34
|
tile.shapes.each do |shape|
|
|
@@ -54,13 +55,12 @@ module Contrek
|
|
|
54
55
|
new_inners = shape.inner_polylines
|
|
55
56
|
new_inner_polylines = []
|
|
56
57
|
tot_inner += Benchmark.measure do
|
|
57
|
-
new_inner_polylines = cursor.join_inners!(new_outer)
|
|
58
|
+
new_inner_polylines = cursor.join_inners!(new_outer, treemap)
|
|
58
59
|
new_inners += new_inner_polylines
|
|
59
60
|
if treemap
|
|
60
|
-
new_inner_polylines.each
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
all_new_inner_polylines << orphan_inner if orphan_inner.recombined
|
|
61
|
+
new_inner_polylines.each do |inner_polyline|
|
|
62
|
+
inner_polyline.sequence.compute_vertical_bounds!
|
|
63
|
+
all_new_inner_polylines += new_inner_polylines
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
new_inners += cursor.orphan_inners
|
|
@@ -70,7 +70,6 @@ module Contrek
|
|
|
70
70
|
inserting_new_shape = Shape.init_by(polyline, new_inners)
|
|
71
71
|
new_shapes << inserting_new_shape
|
|
72
72
|
polyline.shape = inserting_new_shape
|
|
73
|
-
inserting_new_shape.set_parent_shape(shape.parent_shape)
|
|
74
73
|
|
|
75
74
|
new_inner_polylines.each { |inner_polyline| inner_polyline.sequence.shape = inserting_new_shape }
|
|
76
75
|
|
|
@@ -78,23 +77,20 @@ module Contrek
|
|
|
78
77
|
cursor.shapes_sequence.each do |merged_shape|
|
|
79
78
|
merged_shape.merged_to_shape = inserting_new_shape
|
|
80
79
|
end
|
|
81
|
-
|
|
80
|
+
if shape.outer_polyline.inside_inner_polyline
|
|
81
|
+
assign_ancestry(inserting_new_shape, shape.outer_polyline.inside_inner_polyline)
|
|
82
|
+
end
|
|
82
83
|
end
|
|
83
84
|
else
|
|
84
|
-
if treemap
|
|
85
|
-
|
|
85
|
+
if treemap
|
|
86
|
+
if shape.fixed
|
|
87
|
+
shape.set_parent_shape(shape.parent_shape.merged_to_shape) if shape.parent_shape.merged_to_shape
|
|
88
|
+
else
|
|
89
|
+
is_children(shape, all_new_inner_polylines)
|
|
90
|
+
end
|
|
86
91
|
end
|
|
87
|
-
new_shapes << shape
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
92
|
|
|
92
|
-
|
|
93
|
-
@tiles.each do |tile|
|
|
94
|
-
tile.shapes.each do |shape|
|
|
95
|
-
if (merged_to_shape = shape.parent_shape&.merged_to_shape)
|
|
96
|
-
shape.set_parent_shape(merged_to_shape)
|
|
97
|
-
end
|
|
93
|
+
new_shapes << shape
|
|
98
94
|
end
|
|
99
95
|
end
|
|
100
96
|
end
|
|
@@ -116,16 +112,21 @@ module Contrek
|
|
|
116
112
|
|
|
117
113
|
private
|
|
118
114
|
|
|
119
|
-
def assign_ancestry(shape,
|
|
115
|
+
def assign_ancestry(shape, inner_polyline)
|
|
116
|
+
shape.set_parent_shape(inner_polyline.sequence.shape)
|
|
117
|
+
shape.parent_inner_polyline = inner_polyline
|
|
118
|
+
shape.fixed = true
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def is_children(shape, inner_polylines)
|
|
120
122
|
inner_polylines.each do |inner_polyline|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
end
|
|
123
|
+
bounds = inner_polyline.vertical_bounds
|
|
124
|
+
min_y = bounds[:min]
|
|
125
|
+
max_y = bounds[:max]
|
|
126
|
+
next if shape.outer_polyline.get_bounds[:max_y] < min_y ||
|
|
127
|
+
shape.outer_polyline.get_bounds[:min_y] > max_y
|
|
128
|
+
if shape.outer_polyline.within?(inner_polyline.raw)
|
|
129
|
+
assign_ancestry(shape, inner_polyline)
|
|
129
130
|
end
|
|
130
131
|
end
|
|
131
132
|
end
|
|
@@ -4,7 +4,7 @@ module Contrek
|
|
|
4
4
|
attr_reader :orphan_inners, :shapes_sequence
|
|
5
5
|
|
|
6
6
|
def initialize(cluster:, shape:)
|
|
7
|
-
@shapes_sequence =
|
|
7
|
+
@shapes_sequence = [shape]
|
|
8
8
|
@cluster = cluster
|
|
9
9
|
@outer_polyline = shape.outer_polyline
|
|
10
10
|
@orphan_inners = []
|
|
@@ -38,18 +38,19 @@ module Contrek
|
|
|
38
38
|
outer_joined_polyline
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
def join_inners!(outer_seq)
|
|
41
|
+
def join_inners!(outer_seq, treemap)
|
|
42
42
|
return_inner_polylines = []
|
|
43
|
+
shape_index = 0
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
@processing_shapes.each do |shape|
|
|
45
|
+
while shape_index < @shapes_sequence.size
|
|
46
|
+
shape = @shapes_sequence[shape_index]
|
|
47
47
|
polyline = shape.outer_polyline
|
|
48
48
|
polyline.parts.each do |part|
|
|
49
49
|
if part.innerable?
|
|
50
50
|
all_parts = []
|
|
51
|
+
tracked_end_points = []
|
|
51
52
|
bounds = {min: polyline.max_y, max: 0}
|
|
52
|
-
traverse_inner(part, all_parts, bounds)
|
|
53
|
+
traverse_inner(part, all_parts, bounds, tracked_end_points)
|
|
53
54
|
range_of_bounds = (bounds[:min]..bounds[:max])
|
|
54
55
|
|
|
55
56
|
retme_sequence = Sequence.new
|
|
@@ -62,16 +63,36 @@ module Contrek
|
|
|
62
63
|
end
|
|
63
64
|
end
|
|
64
65
|
if retme_sequence.is_not_vertical
|
|
65
|
-
|
|
66
|
+
inner_polyline = InnerPolyline.new(sequence: retme_sequence)
|
|
67
|
+
return_inner_polylines << inner_polyline
|
|
68
|
+
mark_children(tracked_end_points, polyline, inner_polyline) if treemap
|
|
66
69
|
end
|
|
67
70
|
end
|
|
68
71
|
end
|
|
72
|
+
shape_index += 1
|
|
69
73
|
end
|
|
70
74
|
return_inner_polylines
|
|
71
75
|
end
|
|
72
76
|
|
|
73
77
|
private
|
|
74
78
|
|
|
79
|
+
# finds each part (and relative polyline) inscribed between two end_points and sets the
|
|
80
|
+
# founded inner_polyline which be later used to define in which parent hole is placed.
|
|
81
|
+
def mark_children(end_points, outer_polyline, inner_polyline)
|
|
82
|
+
end_points.each_slice(2) do |a, b|
|
|
83
|
+
range = [a.position[:y], b.position[:y]].sort
|
|
84
|
+
(range[0] + 1).upto(range[1] - 1) do |y|
|
|
85
|
+
if (end_point = @cluster.hub.payloads[y])
|
|
86
|
+
end_point.queues.each do |part|
|
|
87
|
+
if part.polyline != outer_polyline
|
|
88
|
+
part.polyline.inside_inner_polyline = inner_polyline
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
75
96
|
# rubocop:disable Lint/NonLocalExitFromIterator
|
|
76
97
|
def traverse_outer(act_part, all_parts, shapes_sequence, outer_joined_polyline)
|
|
77
98
|
last_part = all_parts.last
|
|
@@ -104,7 +125,7 @@ module Contrek
|
|
|
104
125
|
cont = false if map.size == 1 && map.first == Part::SEAM
|
|
105
126
|
end
|
|
106
127
|
if cont
|
|
107
|
-
shapes_sequence.
|
|
128
|
+
shapes_sequence << part.polyline.shape if !shapes_sequence.include?(part.polyline.shape)
|
|
108
129
|
part.next_position(new_position)
|
|
109
130
|
part.dead_end = true
|
|
110
131
|
traverse_outer(part, all_parts, shapes_sequence, outer_joined_polyline)
|
|
@@ -120,7 +141,7 @@ module Contrek
|
|
|
120
141
|
traverse_outer(act_part.circular_next, all_parts, shapes_sequence, outer_joined_polyline)
|
|
121
142
|
end
|
|
122
143
|
|
|
123
|
-
def traverse_inner(act_part, all_parts, bounds)
|
|
144
|
+
def traverse_inner(act_part, all_parts, bounds, tracked_end_points)
|
|
124
145
|
return if act_part == all_parts.first
|
|
125
146
|
|
|
126
147
|
if act_part.size > 0
|
|
@@ -140,6 +161,8 @@ module Contrek
|
|
|
140
161
|
dest_part_versus = dest_part.versus
|
|
141
162
|
next if dest_part_versus != 0 && dest_part_versus == act_part.versus
|
|
142
163
|
|
|
164
|
+
tracked_end_points << act_part.head.end_point
|
|
165
|
+
|
|
143
166
|
link_seq = dest_part.continuum_to?(act_part)
|
|
144
167
|
if link_seq.any?
|
|
145
168
|
ins_part = Part.new(Part::ADDED, act_part.polyline)
|
|
@@ -150,13 +173,13 @@ module Contrek
|
|
|
150
173
|
end
|
|
151
174
|
shape = dest_part.polyline.shape
|
|
152
175
|
if !dest_part.polyline.on?(Polyline::TRACKED_OUTER)
|
|
153
|
-
@
|
|
176
|
+
@shapes_sequence << shape
|
|
154
177
|
@orphan_inners += shape.inner_polylines
|
|
155
178
|
end
|
|
156
179
|
dest_part.polyline.turn_on(Polyline::TRACKED_OUTER)
|
|
157
180
|
if !dest_part.touched
|
|
158
181
|
dest_part.touch!
|
|
159
|
-
traverse_inner(dest_part.circular_next, all_parts, bounds)
|
|
182
|
+
traverse_inner(dest_part.circular_next, all_parts, bounds, tracked_end_points)
|
|
160
183
|
return
|
|
161
184
|
end
|
|
162
185
|
end
|
|
@@ -165,7 +188,7 @@ module Contrek
|
|
|
165
188
|
end
|
|
166
189
|
end
|
|
167
190
|
elsif act_part.next
|
|
168
|
-
traverse_inner(act_part.next, all_parts, bounds)
|
|
191
|
+
traverse_inner(act_part.next, all_parts, bounds, tracked_end_points)
|
|
169
192
|
end
|
|
170
193
|
end
|
|
171
194
|
# rubocop:enable Lint/NonLocalExitFromIterator
|