contrek 1.1.9 → 1.2.1
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 +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +30 -9
- data/Rakefile +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/CMakeLists.txt +10 -12
- data/ext/cpp_polygon_finder/PolygonFinder/examples/example.cpp +6 -0
- 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 +2 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.cpp +66 -158
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.h +0 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/EndPoint.h +4 -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/Part.cpp +0 -13
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.h +1 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.cpp +0 -128
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.h +0 -6
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +0 -50
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +2 -8
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.cpp +22 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Queueable.h +1 -57
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.cpp +0 -12
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.h +0 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.cpp +11 -3
- data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +10 -0
- data/lib/contrek/finder/concurrent/cluster.rb +2 -3
- data/lib/contrek/finder/concurrent/cursor.rb +56 -120
- data/lib/contrek/finder/concurrent/end_point.rb +2 -0
- data/lib/contrek/finder/concurrent/hub.rb +1 -1
- data/lib/contrek/finder/concurrent/part.rb +2 -20
- data/lib/contrek/finder/concurrent/partitionable.rb +0 -81
- data/lib/contrek/finder/concurrent/polyline.rb +3 -47
- data/lib/contrek/finder/concurrent/position.rb +8 -2
- data/lib/contrek/finder/concurrent/queueable.rb +0 -41
- data/lib/contrek/finder/concurrent/tile.rb +0 -4
- data/lib/contrek/finder/concurrent/vertical_merger.rb +9 -5
- data/lib/contrek/version.rb +1 -1
- metadata +3 -3
- /data/{LICENSE-MIT.md → lib/LICENSE-MIT.md} +0 -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;
|
|
@@ -61,19 +61,6 @@ void Part::touch()
|
|
|
61
61
|
{ this->touched_ = true;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
bool Part::intersect_part(Part* other_part)
|
|
65
|
-
{ bool intersect = false;
|
|
66
|
-
other_part->each([&](QNode<Point>* pos) -> bool {
|
|
67
|
-
Position *position = static_cast<Position*>(pos);
|
|
68
|
-
if (position->end_point()->queues_include(this))
|
|
69
|
-
{ intersect = true;
|
|
70
|
-
return(false);
|
|
71
|
-
}
|
|
72
|
-
return(true);
|
|
73
|
-
});
|
|
74
|
-
return(intersect);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
64
|
void Part::orient()
|
|
78
65
|
{ if (this->size <= 1 || (this->size == 2 && this->inverts)) {
|
|
79
66
|
this->versus_ = 0;
|
|
@@ -28,10 +28,10 @@ class Part : public Queueable<Point> {
|
|
|
28
28
|
ADDED = 2
|
|
29
29
|
};
|
|
30
30
|
explicit Part(Types type, Polyline* polyline);
|
|
31
|
+
bool listable() const override { return true; }
|
|
31
32
|
bool is(Types type);
|
|
32
33
|
bool inverts = false;
|
|
33
34
|
bool trasmuted = false;
|
|
34
|
-
bool delayed = false;
|
|
35
35
|
bool dead_end = false;
|
|
36
36
|
Part* next = nullptr;
|
|
37
37
|
Part* prev = nullptr;
|
|
@@ -45,8 +45,6 @@ class Part : public Queueable<Point> {
|
|
|
45
45
|
const bool touched() const { return touched_; }
|
|
46
46
|
const int versus() const { return versus_; }
|
|
47
47
|
void touch();
|
|
48
|
-
bool intersect_part(Part* other_part);
|
|
49
|
-
void set_polyline(Polyline* polyline) { this->polyline_ = polyline; }
|
|
50
48
|
void orient();
|
|
51
49
|
std::string inspect();
|
|
52
50
|
std::vector<EndPoint*> continuum_to(const Part& other_part) const;
|
|
@@ -35,17 +35,6 @@ void Partitionable::add_part(Part* new_part)
|
|
|
35
35
|
if (new_part->is(Part::SEAM)) new_part->orient();
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
void Partitionable::insert_after(Part* part, Part* new_part) {
|
|
39
|
-
auto it = std::find(parts_.begin(), parts_.end(), part);
|
|
40
|
-
if (it != parts_.end()) parts_.insert(it + 1, new_part);
|
|
41
|
-
new_part->prev = part;
|
|
42
|
-
new_part->next = part->next;
|
|
43
|
-
new_part->circular_next = part->next;
|
|
44
|
-
if (part->next) part->next->prev = new_part;
|
|
45
|
-
part->next = new_part;
|
|
46
|
-
part->circular_next = new_part;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
38
|
void Partitionable::partition()
|
|
50
39
|
{ this->parts_.clear();
|
|
51
40
|
Polyline *polyline = static_cast<Polyline*>(this);
|
|
@@ -79,123 +68,6 @@ void Partitionable::partition()
|
|
|
79
68
|
this->trasmute_parts();
|
|
80
69
|
}
|
|
81
70
|
|
|
82
|
-
Part* Partitionable::find_first_part_by_position(Position* position, int versus) {
|
|
83
|
-
for (Part* part : this->parts_)
|
|
84
|
-
{ if ( part->is(Part::SEAM) &&
|
|
85
|
-
part->versus() == -(versus) &&
|
|
86
|
-
position->end_point()->queues_include(part)) return(part);
|
|
87
|
-
}
|
|
88
|
-
return(nullptr);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
std::optional<SewReturnData> Partitionable::sew(std::vector<std::pair<int, int>> intersection, Polyline* other)
|
|
92
|
-
{ std::vector<int> matching_part_indexes;
|
|
93
|
-
std::vector<int> other_matching_part_indexes;
|
|
94
|
-
matching_part_indexes.reserve(intersection.size());
|
|
95
|
-
other_matching_part_indexes.reserve(intersection.size());
|
|
96
|
-
|
|
97
|
-
// traspose
|
|
98
|
-
for (const auto& pair : intersection) {
|
|
99
|
-
matching_part_indexes.push_back(pair.first);
|
|
100
|
-
other_matching_part_indexes.push_back(pair.second);
|
|
101
|
-
}
|
|
102
|
-
std::sort(matching_part_indexes.begin(), matching_part_indexes.end());
|
|
103
|
-
std::sort(other_matching_part_indexes.begin(), other_matching_part_indexes.end());
|
|
104
|
-
|
|
105
|
-
auto start_it_before = other->parts_.begin() + other_matching_part_indexes.back() + 1;
|
|
106
|
-
auto end_it_before = other->parts_.end();
|
|
107
|
-
std::vector<Part*> before_parts(start_it_before, end_it_before);
|
|
108
|
-
auto start_it_after = other->parts_.begin();
|
|
109
|
-
auto end_it_after = other->parts_.begin() + other_matching_part_indexes.front();
|
|
110
|
-
std::vector<Part*> after_parts(start_it_after, end_it_after);
|
|
111
|
-
|
|
112
|
-
int start_idx = matching_part_indexes.front();
|
|
113
|
-
int end_idx = matching_part_indexes.back();
|
|
114
|
-
Part* part_start = parts_[start_idx];
|
|
115
|
-
Part* part_end = parts_[end_idx];
|
|
116
|
-
|
|
117
|
-
auto collect_sequences = [&](const std::vector<int>& indices, std::vector<Part*>& p_list)
|
|
118
|
-
-> std::vector<std::vector<Point*>> {
|
|
119
|
-
std::vector<std::vector<Point*>> result;
|
|
120
|
-
int last_n = -1;
|
|
121
|
-
if (indices.size() < 2) return result;
|
|
122
|
-
for (int n = indices.front() + 1; n < indices.back(); ++n) {
|
|
123
|
-
if (std::find(indices.begin(), indices.end(), n) == indices.end()) {
|
|
124
|
-
Part* part = p_list[n];
|
|
125
|
-
if (part->is(Part::SEAM) && part->size > 0 && !part->delayed) {
|
|
126
|
-
part->delayed = true;
|
|
127
|
-
result.clear();
|
|
128
|
-
result.push_back({nullptr});
|
|
129
|
-
return result;
|
|
130
|
-
}
|
|
131
|
-
if (last_n == (n - 1) && !result.empty()) {
|
|
132
|
-
std::vector<Point*> pts = part->to_vector();
|
|
133
|
-
result.back().insert(result.back().end(), pts.begin(), pts.end());
|
|
134
|
-
} else {
|
|
135
|
-
result.push_back(part->to_vector());
|
|
136
|
-
}
|
|
137
|
-
last_n = n;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
return result;
|
|
141
|
-
};
|
|
142
|
-
auto left = collect_sequences(matching_part_indexes, this->parts_);
|
|
143
|
-
if (!left.empty() && !left[0].empty() && left[0][0] == nullptr) {
|
|
144
|
-
return std::nullopt;
|
|
145
|
-
}
|
|
146
|
-
auto right = collect_sequences(other_matching_part_indexes, other->parts_);
|
|
147
|
-
if (!right.empty() && !right[0].empty() && right[0][0] == nullptr) {
|
|
148
|
-
return std::nullopt;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (part_start != part_end) {
|
|
152
|
-
for (int n = end_idx - 1; n > start_idx; --n) {
|
|
153
|
-
Part* delete_part = parts_[n];
|
|
154
|
-
// Topological detachment of pointers
|
|
155
|
-
if (delete_part->prev) delete_part->prev->next = delete_part->next;
|
|
156
|
-
if (delete_part->next) delete_part->next->prev = delete_part->prev;
|
|
157
|
-
parts_.erase(parts_.begin() + n);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
std::vector<Part*> all_parts;
|
|
162
|
-
Polyline* polyline = static_cast<Polyline*>(this);
|
|
163
|
-
all_parts.reserve(before_parts.size() + after_parts.size());
|
|
164
|
-
all_parts.insert(all_parts.end(), before_parts.begin(), before_parts.end());
|
|
165
|
-
all_parts.insert(all_parts.end(), after_parts.begin(), after_parts.end());
|
|
166
|
-
Part* will_be_last = all_parts.empty() ? nullptr : all_parts.back();
|
|
167
|
-
for (auto it = all_parts.rbegin(); it != all_parts.rend(); ++it) {
|
|
168
|
-
Part* p = *it;
|
|
169
|
-
this->insert_after(part_start, p);
|
|
170
|
-
auto& op = other->parts_;
|
|
171
|
-
op.erase(std::remove(op.begin(), op.end(), p), op.end());
|
|
172
|
-
p->set_polyline(polyline);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
part_start->type = Part::EXCLUSIVE;
|
|
176
|
-
PartPool& pool = polyline->tile->cluster->parts_pool;
|
|
177
|
-
Part* new_end_part = pool.acquire(Part::EXCLUSIVE, polyline);
|
|
178
|
-
new_end_part->add(part_end->tail);
|
|
179
|
-
part_start->singleton();
|
|
180
|
-
|
|
181
|
-
// deletes part_end
|
|
182
|
-
if (part_start != part_end) {
|
|
183
|
-
if (part_end->prev) part_end->prev->next = part_end->next;
|
|
184
|
-
if (part_end->next) part_end->next->prev = part_end->prev;
|
|
185
|
-
auto it = std::find(parts_.begin(), parts_.end(), part_end);
|
|
186
|
-
if (it != parts_.end()) {
|
|
187
|
-
parts_.erase(it);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
Part* reference_part = (will_be_last != nullptr) ? will_be_last : part_start;
|
|
192
|
-
this->insert_after(reference_part, new_end_part);
|
|
193
|
-
|
|
194
|
-
polyline->reset_tracked_endpoints();
|
|
195
|
-
|
|
196
|
-
return std::make_pair(left, right);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
71
|
void Partitionable::trasmute_parts()
|
|
200
72
|
{ std::vector<Part*> insides;
|
|
201
73
|
for (Part* p : parts_) {
|
|
@@ -10,18 +10,13 @@
|
|
|
10
10
|
#pragma once
|
|
11
11
|
#include <vector>
|
|
12
12
|
#include <utility>
|
|
13
|
-
#include <optional>
|
|
14
13
|
#include "Part.h"
|
|
15
14
|
|
|
16
|
-
using SewReturnData = std::pair<std::vector<std::vector<Point*>>, std::vector<std::vector<Point*>>>;
|
|
17
|
-
|
|
18
15
|
class Partitionable {
|
|
19
16
|
public:
|
|
20
17
|
explicit Partitionable() {}
|
|
21
18
|
virtual ~Partitionable() = default;
|
|
22
19
|
void partition();
|
|
23
|
-
Part* find_first_part_by_position(Position* position, int versus);
|
|
24
|
-
std::optional<SewReturnData> sew(std::vector<std::pair<int, int>> intersection, Polyline* other);
|
|
25
20
|
const std::vector<Part*> parts() const { return parts_; }
|
|
26
21
|
|
|
27
22
|
protected:
|
|
@@ -29,6 +24,5 @@ class Partitionable {
|
|
|
29
24
|
|
|
30
25
|
private:
|
|
31
26
|
void add_part(Part* new_part);
|
|
32
|
-
void insert_after(Part* part, Part* new_part);
|
|
33
27
|
void trasmute_parts();
|
|
34
28
|
};
|
|
@@ -29,15 +29,6 @@ Polyline::Polyline(Tile* tile, const std::vector<Point*>& polygon, const std::op
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
void Polyline::precalc() {
|
|
33
|
-
next_tile_eligible_shapes_.clear(); // useless if called once
|
|
34
|
-
for (Shape* s : tile->circular_next->boundary_shapes())
|
|
35
|
-
{ if (!s->outer_polyline->is_on(Polyline::TRACKED_OUTER) && this->vert_intersect(*s->outer_polyline) )
|
|
36
|
-
{ next_tile_eligible_shapes_.push_back(s);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
32
|
bool Polyline::vert_intersect(Polyline& other) {
|
|
42
33
|
return( !(this->max_y_ < other.min_y || other.max_y_ < this->min_y));
|
|
43
34
|
}
|
|
@@ -51,10 +42,6 @@ bool Polyline::boundary() {
|
|
|
51
42
|
return( tile->tg_border(Point{min_x, 0}) || tile->tg_border(Point{max_x, 0}));
|
|
52
43
|
}
|
|
53
44
|
|
|
54
|
-
void Polyline::reset_tracked_endpoints() {
|
|
55
|
-
tracked_endpoints.clear();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
45
|
void Polyline::find_boundary() {
|
|
59
46
|
if (raw_.empty()) return;
|
|
60
47
|
min_x = std::numeric_limits<int>::max();
|
|
@@ -72,43 +59,6 @@ void Polyline::find_boundary() {
|
|
|
72
59
|
}
|
|
73
60
|
}
|
|
74
61
|
|
|
75
|
-
std::vector<std::pair<int, int>> Polyline::intersection(const Polyline* other) const {
|
|
76
|
-
if (this->tracked_endpoints.empty()) {
|
|
77
|
-
for (int i = 0; i < parts_.size(); ++i) {
|
|
78
|
-
auto& part = parts_[i];
|
|
79
|
-
if (!part->is(Part::SEAM) && part->trasmuted) continue;
|
|
80
|
-
part->each([&](QNode<Point>* pos) -> bool {
|
|
81
|
-
Position *position = static_cast<Position*>(pos);
|
|
82
|
-
if (position->end_point() != nullptr)
|
|
83
|
-
{ this->tracked_endpoints[position->end_point()] = i;
|
|
84
|
-
}
|
|
85
|
-
return true;
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
std::vector<std::pair<int, int>> matching_parts;
|
|
91
|
-
for (int j = 0; j < other->parts_.size(); ++j) {
|
|
92
|
-
auto& other_part = other->parts_[j];
|
|
93
|
-
if (!other_part->is(Part::SEAM) && other_part->trasmuted) {
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
other_part->each([&](QNode<Point>* pos) -> bool {
|
|
97
|
-
Position *position = static_cast<Position*>(pos);
|
|
98
|
-
auto it = this->tracked_endpoints.find(position->end_point());
|
|
99
|
-
if (it != this->tracked_endpoints.end()) {
|
|
100
|
-
int self_index = it->second;
|
|
101
|
-
matching_parts.push_back({self_index, j});
|
|
102
|
-
return false;
|
|
103
|
-
}
|
|
104
|
-
return true;
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return matching_parts;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
62
|
void Polyline::clear() {
|
|
113
63
|
this->raw_.clear();
|
|
114
64
|
}
|
|
@@ -29,8 +29,7 @@ class Polyline : public Partitionable {
|
|
|
29
29
|
using Partitionable::Partitionable;
|
|
30
30
|
Polyline(Tile* tile, const std::vector<Point*>& polygon, const std::optional<RectBounds>& bounds = std::nullopt);
|
|
31
31
|
enum Flags : uint32_t {
|
|
32
|
-
TRACKED_OUTER = 1 << 0
|
|
33
|
-
TRACKED_INNER = 1 << 1
|
|
32
|
+
TRACKED_OUTER = 1 << 0
|
|
34
33
|
};
|
|
35
34
|
void turn_on(Flags f) { flags_ |= f; }
|
|
36
35
|
void turn_off(Flags f) { flags_ &= ~f; }
|
|
@@ -41,15 +40,12 @@ class Polyline : public Partitionable {
|
|
|
41
40
|
Tile *tile = nullptr;
|
|
42
41
|
Shape* shape = nullptr;
|
|
43
42
|
std::vector<Point*> raw() const { return raw_; }
|
|
44
|
-
const std::list<Shape*>& next_tile_eligible_shapes() const { return next_tile_eligible_shapes_; }
|
|
45
43
|
const std::vector<Part*>& parts() const { return parts_; }
|
|
46
|
-
std::vector<std::pair<int, int>> intersection(const Polyline* other) const;
|
|
47
44
|
const int max_y() const { return max_y_; }
|
|
48
45
|
void clear();
|
|
49
46
|
bool is_empty();
|
|
50
47
|
bool vert_intersect(Polyline& other);
|
|
51
|
-
|
|
52
|
-
bool mixed_tile_origin = false;
|
|
48
|
+
bool any_ancients = false;
|
|
53
49
|
std::string info();
|
|
54
50
|
bool vert_bounds_intersect(Bounds& vertical_bounds);
|
|
55
51
|
bool within(std::vector<Point*>& points);
|
|
@@ -59,6 +55,4 @@ class Polyline : public Partitionable {
|
|
|
59
55
|
int min_x, max_x, min_y, max_y_;
|
|
60
56
|
void find_boundary();
|
|
61
57
|
uint32_t flags_ = 0;
|
|
62
|
-
std::list<Shape*> next_tile_eligible_shapes_;
|
|
63
|
-
mutable std::unordered_map<const EndPoint*, int> tracked_endpoints;
|
|
64
58
|
};
|
|
@@ -7,8 +7,11 @@
|
|
|
7
7
|
* See the LICENSE file in this directory for the full license text.
|
|
8
8
|
*/
|
|
9
9
|
#include <iostream>
|
|
10
|
+
#include <algorithm>
|
|
10
11
|
#include "Position.h"
|
|
11
12
|
#include "Hub.h"
|
|
13
|
+
#include "Part.h"
|
|
14
|
+
#include "Polyline.h"
|
|
12
15
|
|
|
13
16
|
Position::Position(Hub* hub, Point* point)
|
|
14
17
|
: QNode<Point>(point)
|
|
@@ -30,9 +33,25 @@ Position::Position(EndPoint* end_point)
|
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
void Position::before_rem(Queueable<Point>* q) {
|
|
33
|
-
if (this->end_point_ != nullptr)
|
|
36
|
+
/*if (this->end_point_ != nullptr)
|
|
37
|
+
{ if (q->listable())
|
|
38
|
+
{ auto& v = this->end_point_->queues();
|
|
39
|
+
v.erase(std::remove(v.begin(), v.end(), q), v.end());
|
|
40
|
+
}
|
|
41
|
+
}*/
|
|
34
42
|
}
|
|
35
43
|
|
|
36
|
-
void Position::after_add(Queueable<Point>* q)
|
|
37
|
-
if (this->end_point_ != nullptr
|
|
44
|
+
void Position::after_add(Queueable<Point>* q) {
|
|
45
|
+
if (this->end_point_ != nullptr && q->listable()) {
|
|
46
|
+
auto& q_vec = this->end_point_->queues();
|
|
47
|
+
auto it = std::find(q_vec.begin(), q_vec.end(), q);
|
|
48
|
+
if (it == q_vec.end()) {
|
|
49
|
+
q_vec.push_back(q);
|
|
50
|
+
if (q_vec.size() > 1) {
|
|
51
|
+
static_cast<Part*>(q)->polyline()->any_ancients = true;
|
|
52
|
+
Queueable<Point>* first_q = q_vec.front();
|
|
53
|
+
static_cast<Part*>(first_q)->polyline()->any_ancients = true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
38
57
|
}
|
|
@@ -39,6 +39,7 @@ class Queueable {
|
|
|
39
39
|
QNode<T>* _iterator {nullptr};
|
|
40
40
|
bool _started = false;
|
|
41
41
|
size_t size {0};
|
|
42
|
+
virtual bool listable() const { return false; }
|
|
42
43
|
Queueable() = default;
|
|
43
44
|
virtual ~Queueable() = default;
|
|
44
45
|
|
|
@@ -75,53 +76,6 @@ class Queueable {
|
|
|
75
76
|
node->after_add(this);
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
void reset() {
|
|
79
|
-
head = nullptr;
|
|
80
|
-
tail = nullptr;
|
|
81
|
-
_iterator = nullptr;
|
|
82
|
-
_started = false;
|
|
83
|
-
size = 0;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
void singleton()
|
|
87
|
-
{ if (head && head->next) {
|
|
88
|
-
head->next->prev = nullptr;
|
|
89
|
-
head->next = nullptr;
|
|
90
|
-
}
|
|
91
|
-
tail = nullptr;
|
|
92
|
-
size = 1;
|
|
93
|
-
_iterator = nullptr;
|
|
94
|
-
_started = false;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
void replace(Queueable<T>& q) {
|
|
98
|
-
reset();
|
|
99
|
-
append(q);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
void append(Queueable<T>& q) {
|
|
103
|
-
if (q.size == 0) return;
|
|
104
|
-
QNode<T>* current = q.head;
|
|
105
|
-
while (current) {
|
|
106
|
-
current->before_rem(&q);
|
|
107
|
-
current->owner = this;
|
|
108
|
-
current = current->next;
|
|
109
|
-
}
|
|
110
|
-
if (tail) {
|
|
111
|
-
tail->next = q.head;
|
|
112
|
-
q.head->prev = tail;
|
|
113
|
-
} else {
|
|
114
|
-
head = q.head;
|
|
115
|
-
}
|
|
116
|
-
tail = q.tail;
|
|
117
|
-
size += q.size;
|
|
118
|
-
q.reset();
|
|
119
|
-
each([&](QNode<T>* n) -> bool {
|
|
120
|
-
n->after_add(this);
|
|
121
|
-
return(true);
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
79
|
void rewind() {
|
|
126
80
|
_iterator = nullptr;
|
|
127
81
|
_started = false;
|
|
@@ -198,14 +152,4 @@ class Queueable {
|
|
|
198
152
|
if (!tail) return nullptr;
|
|
199
153
|
return rem(tail);
|
|
200
154
|
}
|
|
201
|
-
|
|
202
|
-
bool contains(const T& value) const {
|
|
203
|
-
QNode<T>* current = head;
|
|
204
|
-
while (current) {
|
|
205
|
-
if (current->payload == value)
|
|
206
|
-
return true;
|
|
207
|
-
current = current->next;
|
|
208
|
-
}
|
|
209
|
-
return false;
|
|
210
|
-
}
|
|
211
155
|
};
|
|
@@ -104,18 +104,6 @@ std::string Tile::toString() {
|
|
|
104
104
|
return s;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
const std::list<Shape*>& Tile::boundary_shapes()
|
|
108
|
-
{ if (!boundary_shapes_initialized_)
|
|
109
|
-
{ for (Shape* s : shapes_)
|
|
110
|
-
{ if (s->outer_polyline->boundary())
|
|
111
|
-
{ boundary_shapes_.push_back(s);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
boundary_shapes_initialized_ = true;
|
|
115
|
-
}
|
|
116
|
-
return boundary_shapes_;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
107
|
std::list<Polygon> Tile::to_raw_polygons()
|
|
120
108
|
{ std::list<Polygon> retme;
|
|
121
109
|
for (Shape* s : shapes_)
|
|
@@ -31,8 +31,6 @@ class Tile {
|
|
|
31
31
|
int end_x_;
|
|
32
32
|
std::string name_;
|
|
33
33
|
std::list<Shape*> shapes_;
|
|
34
|
-
std::list<Shape*> boundary_shapes_;
|
|
35
|
-
bool boundary_shapes_initialized_ = false;
|
|
36
34
|
|
|
37
35
|
public:
|
|
38
36
|
Tile(Finder *finder, int start_x, int end_x, std::string name, const Benchmarks& b);
|
|
@@ -46,7 +44,6 @@ class Tile {
|
|
|
46
44
|
std::string name() const { return name_; }
|
|
47
45
|
const std::list<Shape*>& shapes() const { return shapes_; }
|
|
48
46
|
std::list<Shape*>& shapes() { return shapes_; }
|
|
49
|
-
const std::list<Shape*>& boundary_shapes();
|
|
50
47
|
bool whole();
|
|
51
48
|
bool left();
|
|
52
49
|
bool right();
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
#include <vector>
|
|
13
13
|
#include <algorithm>
|
|
14
14
|
#include <utility>
|
|
15
|
+
#include <unordered_set>
|
|
15
16
|
#include "VerticalMerger.h"
|
|
16
17
|
|
|
17
18
|
VerticalMerger::VerticalMerger(int number_of_threads, std::vector<std::string> *options)
|
|
@@ -35,14 +36,21 @@ ProcessResult* VerticalMerger::process_info() {
|
|
|
35
36
|
|
|
36
37
|
void VerticalMerger::transpose(ProcessResult& result) {
|
|
37
38
|
std::swap(result.width, result.height);
|
|
38
|
-
|
|
39
|
+
std::unordered_set<Point*> seen;
|
|
39
40
|
for (auto& polygon : result.polygons) {
|
|
41
|
+
auto process_p = [&](Point* p) {
|
|
42
|
+
if (p) {
|
|
43
|
+
if (seen.insert(p).second) {
|
|
44
|
+
std::swap(p->x, p->y);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
40
48
|
for (Point* p : polygon.outer) {
|
|
41
|
-
|
|
49
|
+
process_p(p);
|
|
42
50
|
}
|
|
43
51
|
for (auto& sequence : polygon.inner) {
|
|
44
52
|
for (Point* p : sequence) {
|
|
45
|
-
|
|
53
|
+
process_p(p);
|
|
46
54
|
}
|
|
47
55
|
}
|
|
48
56
|
std::swap(polygon.bounds.min_x, polygon.bounds.min_y);
|
|
@@ -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,13 @@ 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
|
+
);
|
|
297
|
+
#endif
|
|
298
|
+
|
|
289
299
|
Data_Type<Bitmap> rb_cBitmap =
|
|
290
300
|
define_class<Bitmap>("CPPBitMap")
|
|
291
301
|
.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)
|
|
@@ -34,7 +34,6 @@ module Contrek
|
|
|
34
34
|
next if shape.outer_polyline.on?(Polyline::TRACKED_OUTER) || shape.outer_polyline.width == 0
|
|
35
35
|
if shape.outer_polyline.boundary?
|
|
36
36
|
shape.outer_polyline.partition!
|
|
37
|
-
shape.outer_polyline.precalc!
|
|
38
37
|
end
|
|
39
38
|
end
|
|
40
39
|
end
|
|
@@ -44,7 +43,7 @@ module Contrek
|
|
|
44
43
|
tile.shapes.each do |shape|
|
|
45
44
|
next if shape.outer_polyline.on?(Polyline::TRACKED_OUTER) || shape.outer_polyline.width == 0
|
|
46
45
|
|
|
47
|
-
if shape.outer_polyline.
|
|
46
|
+
if shape.outer_polyline.any_ancients
|
|
48
47
|
cursor = Cursor.new(cluster: self, shape: shape)
|
|
49
48
|
|
|
50
49
|
new_outer = nil
|