contrek 1.2.9 → 1.3.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 +7 -0
- data/Gemfile.lock +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +13 -27
- 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 -13
- 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 +59 -9
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.h +6 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.cpp +48 -33
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.h +4 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +13 -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 +20 -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/cursor.rb +0 -3
- 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 +36 -1
- data/lib/contrek/finder/concurrent/partitionable.rb +42 -23
- 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 +5 -5
|
@@ -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();
|
|
@@ -20,6 +20,7 @@ void Merger::add_tile(ProcessResult& result)
|
|
|
20
20
|
{ if (this->height == 0) {
|
|
21
21
|
this->height = result.height;
|
|
22
22
|
}
|
|
23
|
+
this->versus = result.versus;
|
|
23
24
|
int end_x = this->current_x + result.width;
|
|
24
25
|
Tile* tile = new Tile(this, this->current_x, end_x, std::to_string(tiles_.size()), Benchmarks {0, 0});
|
|
25
26
|
tile->assign_raw_polygons(result.polygons, result.treemap);
|
|
@@ -36,9 +37,9 @@ ProcessResult* Merger::process_info() {
|
|
|
36
37
|
|
|
37
38
|
void Merger::translate(ProcessResult& result, int offset) {
|
|
38
39
|
for (auto& polygon : result.polygons) {
|
|
39
|
-
for (Point
|
|
40
|
-
for (
|
|
41
|
-
for (Point
|
|
40
|
+
for (Point& p : polygon.outer) p.x += offset;
|
|
41
|
+
for (auto& seq : polygon.inner) {
|
|
42
|
+
for (Point& p : seq) p.x += offset;
|
|
42
43
|
}
|
|
43
44
|
polygon.bounds.min_x += offset;
|
|
44
45
|
polygon.bounds.max_x += offset;
|
|
@@ -29,7 +29,7 @@ Position* Part::next_position(Position* force_position) {
|
|
|
29
29
|
if (force_position != nullptr)
|
|
30
30
|
{ QNode<Point>* move_to_this = nullptr;
|
|
31
31
|
this->reverse_each([&](QNode<Point>* pos) -> bool {
|
|
32
|
-
if (
|
|
32
|
+
if (pos->payload == force_position->payload) {
|
|
33
33
|
move_to_this = pos;
|
|
34
34
|
return false;
|
|
35
35
|
}
|
|
@@ -46,7 +46,7 @@ Position* Part::next_position(Position* force_position) {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
void Part::add_position(Point
|
|
49
|
+
void Part::add_position(const Point& point) {
|
|
50
50
|
Cluster* c = this->polyline_->tile->cluster;
|
|
51
51
|
Hub* hub = is(EXCLUSIVE) ? nullptr : c->hub();
|
|
52
52
|
c->positions_pool.emplace_back(hub, point);
|
|
@@ -65,7 +65,7 @@ void Part::orient()
|
|
|
65
65
|
{ if (this->size <= 1 || (this->size == 2 && this->inverts)) {
|
|
66
66
|
this->versus_ = 0;
|
|
67
67
|
} else {
|
|
68
|
-
int diff = this->tail->payload
|
|
68
|
+
int diff = this->tail->payload.y - this->head->payload.y;
|
|
69
69
|
if (diff == 0) {
|
|
70
70
|
this->mirror = true;
|
|
71
71
|
this->versus_ = 0;
|
|
@@ -75,6 +75,56 @@ void Part::orient()
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
void Part::try_transmutation() {
|
|
79
|
+
auto& head_queues = static_cast<Position*>(this->head)->end_point()->queues();
|
|
80
|
+
if (head_queues.size() == 1) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
auto other_head_it = std::find_if(head_queues.begin(), head_queues.end(), [this](auto* queueable_ptr) {
|
|
85
|
+
Part* part = static_cast<Part*>(queueable_ptr);
|
|
86
|
+
return part != this && part->polyline()->tile == this->polyline()->tile;
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (other_head_it != head_queues.end()) {
|
|
90
|
+
Part* other_head_part = static_cast<Part*>(*other_head_it);
|
|
91
|
+
auto& tail_queues = static_cast<Position*>(this->tail)->end_point()->queues();
|
|
92
|
+
auto found_in_tail = std::find(tail_queues.begin(), tail_queues.end(), other_head_part);
|
|
93
|
+
if (found_in_tail != tail_queues.end()) {
|
|
94
|
+
if ( (other_head_part->tail->payload.y == tail->payload.y && other_head_part->head->payload.y == head->payload.y) ||
|
|
95
|
+
(other_head_part->tail->payload.y == head->payload.y && other_head_part->head->payload.y == tail->payload.y)) {
|
|
96
|
+
if (this->next == nullptr && other_head_part->prev == nullptr) {
|
|
97
|
+
this->mirror = true;
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
this->type = Part::EXCLUSIVE;
|
|
101
|
+
this->trasmuted = true;
|
|
102
|
+
other_head_part->transmutation_skip = true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
bool Part::within(Part* other) {
|
|
109
|
+
const auto [self_min, self_max] = std::minmax(this->head->payload.y, this->tail->payload.y);
|
|
110
|
+
const auto [other_min, other_max] = std::minmax(other->head->payload.y, other->tail->payload.y);
|
|
111
|
+
return (self_min >= other_min) && (self_max <= other_max);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
bool Part::same_length(Part* other) {
|
|
115
|
+
return( std::abs(this->head->payload.y - this->tail->payload.y) ==
|
|
116
|
+
std::abs(other->head->payload.y - other->tail->payload.y));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
constexpr std::string_view typeToString(Part::Types t) noexcept {
|
|
120
|
+
switch (t) {
|
|
121
|
+
case Part::SEAM: return "SEAM";
|
|
122
|
+
case Part::EXCLUSIVE: return "EXCLUSIVE";
|
|
123
|
+
case Part::ADDED: return "ADDED";
|
|
124
|
+
default: return "UNKNOWN";
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
78
128
|
std::string Part::inspect() {
|
|
79
129
|
size_t part_index = 0;
|
|
80
130
|
auto it = std::find(this->polyline()->parts().begin(), this->polyline()->parts().end(), this);
|
|
@@ -89,10 +139,10 @@ std::string Part::inspect() {
|
|
|
89
139
|
<< " trm=" << this->trasmuted
|
|
90
140
|
<< " touched=" << this->touched_
|
|
91
141
|
<< " dead_end=" << this->dead_end
|
|
92
|
-
<< ", " << this->size << "x) of " << this->polyline()->tile->name()
|
|
93
|
-
<< " (" <<
|
|
142
|
+
<< ", " << this->size << "x) of " << this->polyline()->tile->name() << " " << this->polyline()->named()
|
|
143
|
+
<< " (" << typeToString(type) << ") (";
|
|
94
144
|
this->each([&](QNode<Point>* pos) -> bool {
|
|
95
|
-
ss << pos->payload
|
|
145
|
+
ss << pos->payload.toString();
|
|
96
146
|
return true;
|
|
97
147
|
});
|
|
98
148
|
ss << ")";
|
|
@@ -102,18 +152,18 @@ std::string Part::inspect() {
|
|
|
102
152
|
std::vector<EndPoint*> Part::continuum_to(const Part& other_part) const {
|
|
103
153
|
if (this->size <= 2 && this->inverts && other_part.size <= 2 && other_part.inverts) return {};
|
|
104
154
|
|
|
105
|
-
Point
|
|
155
|
+
const Point& target = other_part.head->payload;
|
|
106
156
|
QNode<Point>* cursor = this->tail;
|
|
107
157
|
|
|
108
158
|
while (cursor != nullptr) {
|
|
109
|
-
if (
|
|
159
|
+
if (cursor->payload == target) {
|
|
110
160
|
QNode<Point>* s = cursor;
|
|
111
161
|
QNode<Point>* o = other_part.head;
|
|
112
162
|
bool match = true;
|
|
113
163
|
int count = 0;
|
|
114
164
|
|
|
115
165
|
while (s != nullptr && o != nullptr) {
|
|
116
|
-
if (!(
|
|
166
|
+
if (!(s->payload == o->payload)) {
|
|
117
167
|
match = false;
|
|
118
168
|
break;
|
|
119
169
|
}
|
|
@@ -32,15 +32,17 @@ class Part : public Queueable<Point> {
|
|
|
32
32
|
bool is(Types type);
|
|
33
33
|
bool inverts = false;
|
|
34
34
|
bool trasmuted = false;
|
|
35
|
+
bool transmutation_skip = false;
|
|
35
36
|
bool dead_end = false;
|
|
36
37
|
bool mirror = false;
|
|
37
38
|
Part* next = nullptr;
|
|
39
|
+
Part* next_seam = nullptr;
|
|
38
40
|
Part* prev = nullptr;
|
|
39
41
|
Part* circular_next = nullptr;
|
|
40
42
|
std::string toString() const { return "Part type = " + std::to_string(static_cast<uint32_t>(type)); }
|
|
41
43
|
Polyline* polyline() { return polyline_; }
|
|
42
44
|
Position* next_position(Position* force_position);
|
|
43
|
-
void add_position(Point
|
|
45
|
+
void add_position(const Point& point);
|
|
44
46
|
Types type;
|
|
45
47
|
bool innerable();
|
|
46
48
|
const bool touched() const { return touched_; }
|
|
@@ -49,6 +51,9 @@ class Part : public Queueable<Point> {
|
|
|
49
51
|
void orient();
|
|
50
52
|
std::string inspect();
|
|
51
53
|
std::vector<EndPoint*> continuum_to(const Part& other_part) const;
|
|
54
|
+
bool within(Part* other);
|
|
55
|
+
bool same_length(Part* other);
|
|
56
|
+
void try_transmutation();
|
|
52
57
|
|
|
53
58
|
private:
|
|
54
59
|
int versus_ = 0;
|
|
@@ -32,18 +32,30 @@ void Partitionable::add_part(Part* new_part)
|
|
|
32
32
|
new_part->prev = last;
|
|
33
33
|
new_part->circular_next = this->parts_.front();
|
|
34
34
|
|
|
35
|
-
if (new_part->is(Part::SEAM))
|
|
35
|
+
if (new_part->is(Part::SEAM)) {
|
|
36
|
+
if (!this->first_seam) {
|
|
37
|
+
this->first_seam = new_part;
|
|
38
|
+
}
|
|
39
|
+
if (this->last_seam) {
|
|
40
|
+
this->last_seam->next_seam = new_part;
|
|
41
|
+
}
|
|
42
|
+
this->last_seam = new_part;
|
|
43
|
+
new_part->orient();
|
|
44
|
+
}
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
void Partitionable::partition()
|
|
39
48
|
{ this->parts_.clear();
|
|
49
|
+
this->first_seam = nullptr;
|
|
50
|
+
this->last_seam = nullptr;
|
|
51
|
+
|
|
40
52
|
Polyline *polyline = static_cast<Polyline*>(this);
|
|
41
53
|
PartPool& pool = polyline->tile->cluster->parts_pool;
|
|
42
54
|
Part *current_part = nullptr;
|
|
43
55
|
int n = 0;
|
|
44
|
-
Point* prev_position = nullptr;
|
|
45
|
-
for (Point
|
|
46
|
-
{ if (polyline->tile->tg_border(
|
|
56
|
+
const Point* prev_position = nullptr;
|
|
57
|
+
for (const Point& position : polyline->raw())
|
|
58
|
+
{ if (polyline->tile->tg_border(position))
|
|
47
59
|
{ if (current_part == nullptr) {
|
|
48
60
|
current_part = pool.acquire(Part::SEAM, polyline);
|
|
49
61
|
} else if (!current_part->is(Part::SEAM)) {
|
|
@@ -56,48 +68,51 @@ void Partitionable::partition()
|
|
|
56
68
|
this->add_part(current_part);
|
|
57
69
|
current_part = pool.acquire(Part::EXCLUSIVE, polyline);
|
|
58
70
|
}
|
|
59
|
-
if (n > 0 && *prev_position ==
|
|
71
|
+
if (n > 0 && *prev_position == position) {
|
|
60
72
|
current_part->inverts = true;
|
|
61
73
|
}
|
|
62
74
|
current_part->add_position(position);
|
|
63
75
|
n++;
|
|
64
|
-
prev_position = position;
|
|
76
|
+
prev_position = &position;
|
|
65
77
|
}
|
|
66
78
|
this->add_part(current_part);
|
|
67
79
|
|
|
68
|
-
this->
|
|
80
|
+
this->transmute_parts();
|
|
69
81
|
}
|
|
70
82
|
|
|
71
|
-
void Partitionable::
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
83
|
+
void Partitionable::transmute_transposed_part(Part* part) {
|
|
84
|
+
if (Part* current_seam = this->first_seam; current_seam != nullptr) {
|
|
85
|
+
while (current_seam != nullptr) {
|
|
86
|
+
if (current_seam != part) {
|
|
87
|
+
if (part->within(current_seam)) {
|
|
88
|
+
if (!part->same_length(current_seam)) {
|
|
89
|
+
part->type = Part::EXCLUSIVE;
|
|
90
|
+
part->trasmuted = true;
|
|
91
|
+
std::vector<Queueable<Point>*>& a = static_cast<Position*>(part->head)->end_point()->queues();
|
|
92
|
+
a.erase(std::remove(a.begin(), a.end(), part), a.end());
|
|
93
|
+
std::vector<Queueable<Point>*>& b = static_cast<Position*>(part->tail)->end_point()->queues();
|
|
94
|
+
b.erase(std::remove(b.begin(), b.end(), part), b.end());
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
current_seam = current_seam->next_seam;
|
|
99
|
+
}
|
|
75
100
|
}
|
|
76
|
-
|
|
101
|
+
}
|
|
77
102
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return false;
|
|
89
|
-
});
|
|
90
|
-
if (count == inside->size) {
|
|
91
|
-
if (count < inside_compare->size) {
|
|
92
|
-
inside->type = Part::EXCLUSIVE;
|
|
93
|
-
inside->trasmuted = true;
|
|
94
|
-
break;
|
|
95
|
-
} else if ( count == inside_compare->size &&
|
|
96
|
-
inside->next == nullptr &&
|
|
97
|
-
inside_compare->prev == nullptr) {
|
|
98
|
-
inside->mirror = true;
|
|
103
|
+
void Partitionable::transmute_parts()
|
|
104
|
+
{ Polyline *polyline = static_cast<Polyline*>(this);
|
|
105
|
+
bool transpose = polyline->tile->cluster->finder()->transpose();
|
|
106
|
+
if (Part* current_seam = this->first_seam; current_seam != nullptr) {
|
|
107
|
+
while (current_seam != nullptr) {
|
|
108
|
+
if (transpose) {
|
|
109
|
+
transmute_transposed_part(current_seam);
|
|
110
|
+
} else {
|
|
111
|
+
if (!current_seam->transmutation_skip) {
|
|
112
|
+
current_seam->try_transmutation();
|
|
99
113
|
}
|
|
100
114
|
}
|
|
115
|
+
current_seam = current_seam->next_seam;
|
|
101
116
|
}
|
|
102
117
|
}
|
|
103
118
|
}
|
|
@@ -21,8 +21,10 @@ class Partitionable {
|
|
|
21
21
|
|
|
22
22
|
protected:
|
|
23
23
|
std::vector<Part*> parts_;
|
|
24
|
-
|
|
24
|
+
Part* first_seam = nullptr;
|
|
25
|
+
Part* last_seam = nullptr;
|
|
25
26
|
private:
|
|
26
27
|
void add_part(Part* new_part);
|
|
27
|
-
void
|
|
28
|
+
void transmute_parts();
|
|
29
|
+
void transmute_transposed_part(Part* part);
|
|
28
30
|
};
|
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
#include <string>
|
|
13
13
|
#include <unordered_set>
|
|
14
14
|
#include <sstream>
|
|
15
|
+
#include <utility>
|
|
15
16
|
#include "Polyline.h"
|
|
16
17
|
#include "Tile.h"
|
|
17
18
|
#include "Shape.h"
|
|
18
19
|
|
|
19
|
-
Polyline::Polyline(Tile* tile,
|
|
20
|
-
: raw_(polygon),
|
|
20
|
+
Polyline::Polyline(Tile* tile, std::vector<Point> polygon, const std::optional<RectBounds>& bounds)
|
|
21
|
+
: raw_(std::move(polygon)),
|
|
21
22
|
tile(tile)
|
|
22
23
|
{ if (bounds.has_value()) {
|
|
23
24
|
min_x = bounds->min_x;
|
|
@@ -45,10 +46,9 @@ void Polyline::find_boundary() {
|
|
|
45
46
|
max_x_ = -std::numeric_limits<int>::max();
|
|
46
47
|
min_y_ = std::numeric_limits<int>::max();
|
|
47
48
|
max_y_ = -std::numeric_limits<int>::max();
|
|
48
|
-
for (Point
|
|
49
|
-
|
|
50
|
-
int
|
|
51
|
-
int y = p->y;
|
|
49
|
+
for (const Point& p : raw_) {
|
|
50
|
+
int x = p.x;
|
|
51
|
+
int y = p.y;
|
|
52
52
|
if (x < min_x) min_x = x;
|
|
53
53
|
if (x > max_x_) max_x_ = x;
|
|
54
54
|
if (y < min_y_) min_y_ = y;
|
|
@@ -68,17 +68,17 @@ bool Polyline::vert_bounds_intersect(Bounds& vertical_bounds)
|
|
|
68
68
|
{ return !(this->max_y_ < vertical_bounds.min || vertical_bounds.max < this->min_y_);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
bool Polyline::within(std::vector<Point
|
|
71
|
+
bool Polyline::within(std::vector<Point>& points) {
|
|
72
72
|
size_t n = points.size();
|
|
73
73
|
if (n < 3) return false;
|
|
74
|
-
const int tx = this->raw_[0]
|
|
75
|
-
const int ty = this->raw_[0]
|
|
74
|
+
const int tx = this->raw_[0].x;
|
|
75
|
+
const int ty = this->raw_[0].y;
|
|
76
76
|
bool inside = false;
|
|
77
77
|
for (size_t i = 0, j = n - 1; i < n; j = i++) {
|
|
78
|
-
const Point
|
|
79
|
-
const Point
|
|
80
|
-
if (((pi
|
|
81
|
-
(tx < (pj
|
|
78
|
+
const Point& pi = points[i];
|
|
79
|
+
const Point& pj = points[j];
|
|
80
|
+
if (((pi.y > ty) != (pj.y > ty)) &&
|
|
81
|
+
(tx < (pj.x - pi.x) * (ty - pi.y) / (pj.y - pi.y) + pi.x)) {
|
|
82
82
|
inside = !inside;
|
|
83
83
|
}
|
|
84
84
|
}
|
|
@@ -28,7 +28,7 @@ class InnerPolyline;
|
|
|
28
28
|
class Polyline : public Partitionable {
|
|
29
29
|
public:
|
|
30
30
|
using Partitionable::Partitionable;
|
|
31
|
-
Polyline(Tile* tile,
|
|
31
|
+
Polyline(Tile* tile, std::vector<Point> polygon, const std::optional<RectBounds>& bounds = std::nullopt);
|
|
32
32
|
enum Flags : uint32_t {
|
|
33
33
|
TRACKED_OUTER = 1 << 0
|
|
34
34
|
};
|
|
@@ -40,7 +40,7 @@ class Polyline : public Partitionable {
|
|
|
40
40
|
int width();
|
|
41
41
|
Tile *tile = nullptr;
|
|
42
42
|
Shape* shape = nullptr;
|
|
43
|
-
const std::vector<Point
|
|
43
|
+
const std::vector<Point>& raw() const { return raw_; }
|
|
44
44
|
const std::vector<Part*>& parts() const { return parts_; }
|
|
45
45
|
const int max_y() const { return max_y_; }
|
|
46
46
|
const int min_y() const { return min_y_; }
|
|
@@ -49,14 +49,14 @@ class Polyline : public Partitionable {
|
|
|
49
49
|
bool is_empty();
|
|
50
50
|
bool any_ancients = false;
|
|
51
51
|
bool vert_bounds_intersect(Bounds& vertical_bounds);
|
|
52
|
-
bool within(std::vector<Point
|
|
52
|
+
bool within(std::vector<Point>& points);
|
|
53
53
|
InnerPolyline* inside_inner_polyline = nullptr;
|
|
54
54
|
std::string named();
|
|
55
55
|
void set_named(std::string force_named) { this->named_ = force_named; }
|
|
56
56
|
void fill_bounds(RectBounds& target_bounds) const;
|
|
57
57
|
|
|
58
58
|
private:
|
|
59
|
-
std::vector<Point
|
|
59
|
+
std::vector<Point> raw_;
|
|
60
60
|
int min_x, max_x_, min_y_, max_y_;
|
|
61
61
|
void find_boundary();
|
|
62
62
|
uint32_t flags_ = 0;
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
#include "Part.h"
|
|
14
14
|
#include "Polyline.h"
|
|
15
15
|
|
|
16
|
-
Position::Position(Hub* hub, Point
|
|
16
|
+
Position::Position(Hub* hub, const Point& point)
|
|
17
17
|
: QNode<Point>(point)
|
|
18
18
|
{ if (hub != nullptr) {
|
|
19
|
-
int key = point
|
|
19
|
+
int key = point.y;
|
|
20
20
|
EndPoint* existing_ep = hub->get(key);
|
|
21
21
|
if (existing_ep == nullptr)
|
|
22
22
|
{ end_point_ = hub->put(key, hub->spawn_end_point());
|
|
@@ -17,7 +17,7 @@ class EndPoint;
|
|
|
17
17
|
class Hub;
|
|
18
18
|
class Position : public QNode<Point>{
|
|
19
19
|
public:
|
|
20
|
-
explicit Position(Hub* hub, Point
|
|
20
|
+
explicit Position(Hub* hub, const Point& point);
|
|
21
21
|
explicit Position(EndPoint* end_point);
|
|
22
22
|
EndPoint* end_point() { return end_point_; }
|
|
23
23
|
void before_rem(Queueable<Point>* q) override;
|
|
@@ -20,11 +20,11 @@ class Queueable;
|
|
|
20
20
|
template <typename T>
|
|
21
21
|
class QNode {
|
|
22
22
|
public:
|
|
23
|
-
T
|
|
23
|
+
T payload;
|
|
24
24
|
QNode<T>* next {nullptr};
|
|
25
25
|
QNode<T>* prev {nullptr};
|
|
26
26
|
Queueable<T>* owner {nullptr};
|
|
27
|
-
explicit QNode(T
|
|
27
|
+
explicit QNode(const T& value) : payload(value) {}
|
|
28
28
|
virtual ~QNode() = default;
|
|
29
29
|
virtual void before_rem(Queueable<T>* q) {}
|
|
30
30
|
virtual void after_add(Queueable<T>* q) {}
|
|
@@ -129,8 +129,8 @@ class Queueable {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
std::vector<T
|
|
133
|
-
std::vector<T
|
|
132
|
+
std::vector<T> to_vector() const {
|
|
133
|
+
std::vector<T> out;
|
|
134
134
|
out.reserve(this->size);
|
|
135
135
|
QNode<T>* current = head;
|
|
136
136
|
while (current) {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
std::string Sequence::toString() {
|
|
14
14
|
std::string retme = "";
|
|
15
15
|
this->each([&](QNode<Point>* pos) -> bool {
|
|
16
|
-
retme += pos->payload
|
|
16
|
+
retme += pos->payload.toString();
|
|
17
17
|
return true;
|
|
18
18
|
});
|
|
19
19
|
return(retme);
|
|
@@ -23,11 +23,11 @@ bool Sequence::is_not_vertical()
|
|
|
23
23
|
{ if (this->size < 2) {
|
|
24
24
|
return false;
|
|
25
25
|
}
|
|
26
|
-
int x0 = head->payload
|
|
26
|
+
int x0 = head->payload.x;
|
|
27
27
|
this->rewind();
|
|
28
28
|
|
|
29
29
|
while (QNode<Point>* position = this->iterator())
|
|
30
|
-
{ if (position->payload
|
|
30
|
+
{ if (position->payload.x != x0) {
|
|
31
31
|
return true;
|
|
32
32
|
}
|
|
33
33
|
this->forward();
|
|
@@ -38,11 +38,11 @@ bool Sequence::is_not_vertical()
|
|
|
38
38
|
void Sequence::compute_vertical_bounds()
|
|
39
39
|
{ const auto& cache = get_vector_cache();
|
|
40
40
|
if (!cache.empty()) {
|
|
41
|
-
int min_y = cache[0]
|
|
42
|
-
int max_y = cache[0]
|
|
41
|
+
int min_y = cache[0].y;
|
|
42
|
+
int max_y = cache[0].y;
|
|
43
43
|
for (const auto& pos : cache) {
|
|
44
|
-
if (pos
|
|
45
|
-
if (pos
|
|
44
|
+
if (pos.y < min_y) min_y = pos.y;
|
|
45
|
+
if (pos.y > max_y) max_y = pos.y;
|
|
46
46
|
}
|
|
47
47
|
vertical_bounds.min = min_y;
|
|
48
48
|
vertical_bounds.max = max_y;
|
|
@@ -24,12 +24,12 @@ class Sequence : public Queueable<Point>{
|
|
|
24
24
|
Shape* shape = nullptr;
|
|
25
25
|
Bounds vertical_bounds;
|
|
26
26
|
void compute_vertical_bounds();
|
|
27
|
-
const std::vector<Point
|
|
27
|
+
const std::vector<Point>& get_vector_cache() {
|
|
28
28
|
if (vector_cache.empty() && this->size > 0) {
|
|
29
29
|
vector_cache = this->to_vector();
|
|
30
30
|
}
|
|
31
31
|
return vector_cache;
|
|
32
32
|
}
|
|
33
33
|
private:
|
|
34
|
-
std::vector<Point
|
|
34
|
+
std::vector<Point> vector_cache;
|
|
35
35
|
};
|
|
@@ -12,10 +12,12 @@
|
|
|
12
12
|
#include <string>
|
|
13
13
|
#include "Shape.h"
|
|
14
14
|
#include "Polyline.h"
|
|
15
|
+
#include "ShapePool.h"
|
|
15
16
|
|
|
16
|
-
Shape::Shape(Polyline* outer_polyline, const std::vector<InnerPolyline*>& inner_polylines)
|
|
17
|
+
Shape::Shape(ShapePool* shape_pool, Polyline* outer_polyline, const std::vector<InnerPolyline*>& inner_polylines)
|
|
17
18
|
: outer_polyline(outer_polyline),
|
|
18
|
-
inner_polylines(inner_polylines)
|
|
19
|
+
inner_polylines(inner_polylines),
|
|
20
|
+
shape_pool_(shape_pool) {
|
|
19
21
|
for (InnerPolyline* ip : inner_polylines) {
|
|
20
22
|
ip->assigned_shape = this;
|
|
21
23
|
}
|
|
@@ -25,6 +27,10 @@ void Shape::clear_inner() {
|
|
|
25
27
|
inner_polylines.clear();
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
void Shape::detach_from_pool() {
|
|
31
|
+
shape_pool_->detach_shape();
|
|
32
|
+
}
|
|
33
|
+
|
|
28
34
|
void Shape::set_parent_shape(Shape* shape) {
|
|
29
35
|
if (this->parent_shape_ != nullptr)
|
|
30
36
|
{ auto& v = this->parent_shape_->children_shapes;
|
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
|
|
17
17
|
class Point;
|
|
18
18
|
class Polyline;
|
|
19
|
+
class ShapePool;
|
|
19
20
|
class Shape {
|
|
20
21
|
public:
|
|
21
|
-
Shape(Polyline* outer_polyline, const std::vector<InnerPolyline*>& inner_polylines);
|
|
22
|
+
Shape(ShapePool* shape_pool, Polyline* outer_polyline, const std::vector<InnerPolyline*>& inner_polylines);
|
|
22
23
|
Polyline* outer_polyline = nullptr;
|
|
23
24
|
std::vector<InnerPolyline*> inner_polylines;
|
|
24
25
|
Shape* merged_to_shape = nullptr;
|
|
@@ -29,6 +30,8 @@ class Shape {
|
|
|
29
30
|
Shape* parent_shape() { return parent_shape_; }
|
|
30
31
|
void set_parent_shape(Shape*);
|
|
31
32
|
std::string name();
|
|
33
|
+
void detach_from_pool();
|
|
32
34
|
private:
|
|
33
35
|
Shape* parent_shape_ = nullptr;
|
|
36
|
+
ShapePool* shape_pool_ = nullptr;
|
|
34
37
|
};
|
|
@@ -8,17 +8,32 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
#include <vector>
|
|
11
|
+
#include <utility>
|
|
11
12
|
#include "Shape.h"
|
|
12
13
|
#include "ShapePool.h"
|
|
14
|
+
#include "Tile.h"
|
|
13
15
|
|
|
14
16
|
Shape* ShapePool::acquire_shape(Polyline* outer_polyline, const std::vector<InnerPolyline*>& inner_polylines) {
|
|
15
|
-
shapes_storage.emplace_back(outer_polyline, inner_polylines);
|
|
17
|
+
shapes_storage.emplace_back(this, outer_polyline, inner_polylines);
|
|
16
18
|
Shape* shape = &shapes_storage.back();
|
|
19
|
+
this->shapes_count++;
|
|
17
20
|
return shape;
|
|
18
21
|
}
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
void ShapePool::set_owner(Tile* tile) {
|
|
24
|
+
this->owner_tile_ = tile;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
void ShapePool::detach_shape() {
|
|
28
|
+
this->shapes_count--;
|
|
29
|
+
if (this->shapes_count == 0) {
|
|
30
|
+
this->owner_tile_->unregister_pool(this);
|
|
31
|
+
delete this;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
InnerPolyline* ShapePool::acquire_inner_polyline(std::vector<Point> coords, Shape* shape) {
|
|
36
|
+
inner_polylines_storage.emplace_back(std::move(coords), shape);
|
|
22
37
|
InnerPolyline* ip = &inner_polylines_storage.back();
|
|
23
38
|
return ip;
|
|
24
39
|
}
|
|
@@ -35,8 +50,8 @@ Sequence* ShapePool::acquire_sequence() {
|
|
|
35
50
|
return s;
|
|
36
51
|
}
|
|
37
52
|
|
|
38
|
-
Polyline* ShapePool::acquire_polyline(Tile* tile,
|
|
39
|
-
polylines_storage.emplace_back(tile, polygon, bounds);
|
|
53
|
+
Polyline* ShapePool::acquire_polyline(Tile* tile, std::vector<Point> polygon, const std::optional<RectBounds>& bounds = std::nullopt) {
|
|
54
|
+
polylines_storage.emplace_back(tile, std::move(polygon), bounds);
|
|
40
55
|
Polyline* p = &polylines_storage.back();
|
|
41
56
|
return p;
|
|
42
57
|
}
|
|
@@ -20,6 +20,8 @@ class Polyline;
|
|
|
20
20
|
class InnerPolyline;
|
|
21
21
|
class ShapePool {
|
|
22
22
|
private:
|
|
23
|
+
int shapes_count = 0;
|
|
24
|
+
Tile* owner_tile_ = nullptr;
|
|
23
25
|
std::deque<Shape> shapes_storage;
|
|
24
26
|
std::deque<InnerPolyline> inner_polylines_storage;
|
|
25
27
|
std::deque<Sequence> sequences_storage;
|
|
@@ -27,8 +29,10 @@ class ShapePool {
|
|
|
27
29
|
|
|
28
30
|
public:
|
|
29
31
|
Shape* acquire_shape(Polyline* outer_polyline, const std::vector<InnerPolyline*>& inner_polylines);
|
|
30
|
-
InnerPolyline* acquire_inner_polyline(std::vector<Point
|
|
32
|
+
InnerPolyline* acquire_inner_polyline(std::vector<Point> coords, Shape* s);
|
|
31
33
|
InnerPolyline* acquire_inner_polyline(Sequence* seq);
|
|
32
34
|
Sequence* acquire_sequence();
|
|
33
|
-
Polyline* acquire_polyline(Tile* tile,
|
|
35
|
+
Polyline* acquire_polyline(Tile* tile, std::vector<Point> polygon, const std::optional<RectBounds>& bounds);
|
|
36
|
+
void set_owner(Tile* tile);
|
|
37
|
+
void detach_shape();
|
|
34
38
|
};
|