contrek 1.2.8 → 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/.gitignore +2 -1
- data/.rubocop.yml +11 -0
- data/CHANGELOG.md +7 -1
- data/Gemfile +2 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/Rakefile +2 -0
- data/contrek.gemspec +2 -0
- data/ext/cpp_polygon_finder/PolygonFinder/CMakeLists.txt +2 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +118 -19
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.h +1 -0
- 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 -13
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +79 -354
- 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 +3 -1
- 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 +18 -19
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +6 -5
- 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 +117 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.h +41 -0
- 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 +66 -16
- data/ext/cpp_polygon_finder/extconf.rb +2 -0
- data/lib/contrek/bitmaps/bitmap.rb +2 -0
- data/lib/contrek/bitmaps/chunky_bitmap.rb +13 -0
- data/lib/contrek/bitmaps/painting.rb +2 -0
- data/lib/contrek/bitmaps/png_bitmap.rb +2 -0
- data/lib/contrek/bitmaps/raw_bitmap.rb +2 -0
- data/lib/contrek/bitmaps/rgb_color.rb +2 -0
- data/lib/contrek/bitmaps/rgb_cpp_color.rb +2 -0
- data/lib/contrek/bitmaps/sample_generator.rb +2 -0
- data/lib/contrek/cpp/cpp_concurrent_finder.rb +2 -0
- data/lib/contrek/cpp/cpp_concurrent_horizontal_merger.rb +2 -0
- data/lib/contrek/cpp/cpp_concurrent_merger.rb +2 -0
- data/lib/contrek/cpp/cpp_concurrent_streaming_merger.rb +11 -0
- data/lib/contrek/cpp/cpp_concurrent_vertical_merger.rb +2 -0
- data/lib/contrek/cpp/cpp_result.rb +2 -0
- data/lib/contrek/cpp/cpp_tempfile.rb +28 -0
- data/lib/contrek/finder/bounds.rb +2 -0
- data/lib/contrek/finder/concurrent/clipped_polygon_finder.rb +2 -0
- data/lib/contrek/finder/concurrent/cluster.rb +3 -1
- data/lib/contrek/finder/concurrent/cursor.rb +2 -0
- data/lib/contrek/finder/concurrent/end_point.rb +2 -0
- data/lib/contrek/finder/concurrent/fake_cluster.rb +2 -0
- data/lib/contrek/finder/concurrent/finder.rb +6 -0
- data/lib/contrek/finder/concurrent/horizontal_merger.rb +2 -0
- data/lib/contrek/finder/concurrent/hub.rb +2 -0
- data/lib/contrek/finder/concurrent/inner_polyline.rb +2 -0
- data/lib/contrek/finder/concurrent/listable.rb +2 -0
- data/lib/contrek/finder/concurrent/merger.rb +4 -0
- data/lib/contrek/finder/concurrent/part.rb +13 -0
- data/lib/contrek/finder/concurrent/partitionable.rb +33 -17
- data/lib/contrek/finder/concurrent/polyline.rb +2 -0
- data/lib/contrek/finder/concurrent/poolable.rb +2 -0
- data/lib/contrek/finder/concurrent/position.rb +2 -0
- data/lib/contrek/finder/concurrent/queueable.rb +2 -0
- data/lib/contrek/finder/concurrent/sequence.rb +2 -0
- data/lib/contrek/finder/concurrent/shape.rb +2 -0
- data/lib/contrek/finder/concurrent/streaming_merger.rb +89 -0
- data/lib/contrek/finder/concurrent/tile.rb +2 -0
- data/lib/contrek/finder/concurrent/vertical_merger.rb +8 -2
- data/lib/contrek/finder/list.rb +2 -0
- data/lib/contrek/finder/list_entry.rb +2 -0
- data/lib/contrek/finder/listable.rb +2 -0
- data/lib/contrek/finder/lists.rb +2 -0
- data/lib/contrek/finder/node.rb +2 -0
- data/lib/contrek/finder/node_cluster.rb +3 -1
- data/lib/contrek/finder/polygon_finder.rb +4 -1
- data/lib/contrek/finder/result.rb +2 -0
- data/lib/contrek/map/mercator_projection.rb +2 -0
- data/lib/contrek/matchers/matcher.rb +2 -0
- data/lib/contrek/matchers/matcher_hsb.rb +2 -0
- data/lib/contrek/matchers/value_not_matcher.rb +2 -0
- data/lib/contrek/reducers/linear_reducer.rb +2 -0
- data/lib/contrek/reducers/reducer.rb +2 -0
- data/lib/contrek/reducers/uniq_reducer.rb +2 -0
- data/lib/contrek/reducers/visvalingam_reducer.rb +2 -0
- data/lib/contrek/shared/result.rb +2 -0
- data/lib/contrek/version.rb +3 -1
- data/lib/contrek.rb +5 -0
- metadata +11 -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,26 @@ void Part::orient()
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
bool Part::within(Part* other) {
|
|
79
|
+
const auto [self_min, self_max] = std::minmax(this->head->payload.y, this->tail->payload.y);
|
|
80
|
+
const auto [other_min, other_max] = std::minmax(other->head->payload.y, other->tail->payload.y);
|
|
81
|
+
return (self_min >= other_min) && (self_max <= other_max);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
bool Part::same_length(Part* other) {
|
|
85
|
+
return( std::abs(this->head->payload.y - this->tail->payload.y) ==
|
|
86
|
+
std::abs(other->head->payload.y - other->tail->payload.y));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
constexpr std::string_view typeToString(Part::Types t) noexcept {
|
|
90
|
+
switch (t) {
|
|
91
|
+
case Part::SEAM: return "SEAM";
|
|
92
|
+
case Part::EXCLUSIVE: return "EXCLUSIVE";
|
|
93
|
+
case Part::ADDED: return "ADDED";
|
|
94
|
+
default: return "UNKNOWN";
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
78
98
|
std::string Part::inspect() {
|
|
79
99
|
size_t part_index = 0;
|
|
80
100
|
auto it = std::find(this->polyline()->parts().begin(), this->polyline()->parts().end(), this);
|
|
@@ -89,10 +109,10 @@ std::string Part::inspect() {
|
|
|
89
109
|
<< " trm=" << this->trasmuted
|
|
90
110
|
<< " touched=" << this->touched_
|
|
91
111
|
<< " dead_end=" << this->dead_end
|
|
92
|
-
<< ", " << this->size << "x) of " << this->polyline()->tile->name()
|
|
93
|
-
<< " (" <<
|
|
112
|
+
<< ", " << this->size << "x) of " << this->polyline()->tile->name() << " " << this->polyline()->named()
|
|
113
|
+
<< " (" << typeToString(type) << ") (";
|
|
94
114
|
this->each([&](QNode<Point>* pos) -> bool {
|
|
95
|
-
ss << pos->payload
|
|
115
|
+
ss << pos->payload.toString();
|
|
96
116
|
return true;
|
|
97
117
|
});
|
|
98
118
|
ss << ")";
|
|
@@ -102,18 +122,18 @@ std::string Part::inspect() {
|
|
|
102
122
|
std::vector<EndPoint*> Part::continuum_to(const Part& other_part) const {
|
|
103
123
|
if (this->size <= 2 && this->inverts && other_part.size <= 2 && other_part.inverts) return {};
|
|
104
124
|
|
|
105
|
-
Point
|
|
125
|
+
const Point& target = other_part.head->payload;
|
|
106
126
|
QNode<Point>* cursor = this->tail;
|
|
107
127
|
|
|
108
128
|
while (cursor != nullptr) {
|
|
109
|
-
if (
|
|
129
|
+
if (cursor->payload == target) {
|
|
110
130
|
QNode<Point>* s = cursor;
|
|
111
131
|
QNode<Point>* o = other_part.head;
|
|
112
132
|
bool match = true;
|
|
113
133
|
int count = 0;
|
|
114
134
|
|
|
115
135
|
while (s != nullptr && o != nullptr) {
|
|
116
|
-
if (!(
|
|
136
|
+
if (!(s->payload == o->payload)) {
|
|
117
137
|
match = false;
|
|
118
138
|
break;
|
|
119
139
|
}
|
|
@@ -40,7 +40,7 @@ class Part : public Queueable<Point> {
|
|
|
40
40
|
std::string toString() const { return "Part type = " + std::to_string(static_cast<uint32_t>(type)); }
|
|
41
41
|
Polyline* polyline() { return polyline_; }
|
|
42
42
|
Position* next_position(Position* force_position);
|
|
43
|
-
void add_position(Point
|
|
43
|
+
void add_position(const Point& point);
|
|
44
44
|
Types type;
|
|
45
45
|
bool innerable();
|
|
46
46
|
const bool touched() const { return touched_; }
|
|
@@ -49,6 +49,8 @@ class Part : public Queueable<Point> {
|
|
|
49
49
|
void orient();
|
|
50
50
|
std::string inspect();
|
|
51
51
|
std::vector<EndPoint*> continuum_to(const Part& other_part) const;
|
|
52
|
+
bool within(Part* other);
|
|
53
|
+
bool same_length(Part* other);
|
|
52
54
|
|
|
53
55
|
private:
|
|
54
56
|
int versus_ = 0;
|
|
@@ -41,9 +41,9 @@ void Partitionable::partition()
|
|
|
41
41
|
PartPool& pool = polyline->tile->cluster->parts_pool;
|
|
42
42
|
Part *current_part = nullptr;
|
|
43
43
|
int n = 0;
|
|
44
|
-
Point* prev_position = nullptr;
|
|
45
|
-
for (Point
|
|
46
|
-
{ if (polyline->tile->tg_border(
|
|
44
|
+
const Point* prev_position = nullptr;
|
|
45
|
+
for (const Point& position : polyline->raw())
|
|
46
|
+
{ if (polyline->tile->tg_border(position))
|
|
47
47
|
{ if (current_part == nullptr) {
|
|
48
48
|
current_part = pool.acquire(Part::SEAM, polyline);
|
|
49
49
|
} else if (!current_part->is(Part::SEAM)) {
|
|
@@ -56,12 +56,12 @@ void Partitionable::partition()
|
|
|
56
56
|
this->add_part(current_part);
|
|
57
57
|
current_part = pool.acquire(Part::EXCLUSIVE, polyline);
|
|
58
58
|
}
|
|
59
|
-
if (n > 0 && *prev_position ==
|
|
59
|
+
if (n > 0 && *prev_position == position) {
|
|
60
60
|
current_part->inverts = true;
|
|
61
61
|
}
|
|
62
62
|
current_part->add_position(position);
|
|
63
63
|
n++;
|
|
64
|
-
prev_position = position;
|
|
64
|
+
prev_position = &position;
|
|
65
65
|
}
|
|
66
66
|
this->add_part(current_part);
|
|
67
67
|
|
|
@@ -69,33 +69,48 @@ void Partitionable::partition()
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
void Partitionable::trasmute_parts()
|
|
72
|
-
{
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
{ Polyline *polyline = static_cast<Polyline*>(this);
|
|
73
|
+
bool transpose = polyline->tile->cluster->finder()->transpose();
|
|
74
|
+
|
|
75
|
+
for (Part* inside : parts_) {
|
|
76
|
+
if (!inside->is(Part::SEAM)) continue;
|
|
77
|
+
for (Part* inside_compare : parts_) {
|
|
78
|
+
if (inside == inside_compare || !inside_compare->is(Part::SEAM)) continue;
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
if (transpose) {
|
|
81
|
+
if (inside->within(inside_compare)) {
|
|
82
|
+
Part* target_part;
|
|
83
|
+
if (!inside->same_length(inside_compare)) {
|
|
84
|
+
target_part = inside;
|
|
85
|
+
target_part->type = Part::EXCLUSIVE;
|
|
86
|
+
target_part->trasmuted = true;
|
|
87
|
+
std::vector<Queueable<Point>*>& a = static_cast<Position*>(target_part->head)->end_point()->queues();
|
|
88
|
+
a.erase(std::remove(a.begin(), a.end(), target_part), a.end());
|
|
89
|
+
std::vector<Queueable<Point>*>& b = static_cast<Position*>(target_part->tail)->end_point()->queues();
|
|
90
|
+
b.erase(std::remove(b.begin(), b.end(), target_part), b.end());
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
87
93
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
} else {
|
|
95
|
+
int count = 0;
|
|
96
|
+
inside->each([&](QNode<Point>* pos) -> bool {
|
|
97
|
+
Position *position = static_cast<Position*>(pos);
|
|
98
|
+
if (position->end_point()->queues_include(inside_compare))
|
|
99
|
+
{ count++;
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
});
|
|
104
|
+
if (count == inside->size) {
|
|
105
|
+
if (count < inside_compare->size) {
|
|
106
|
+
inside->type = Part::EXCLUSIVE;
|
|
107
|
+
inside->trasmuted = true;
|
|
108
|
+
break;
|
|
109
|
+
} else if ( count == inside_compare->size &&
|
|
110
|
+
inside->next == nullptr &&
|
|
111
|
+
inside_compare->prev == nullptr) {
|
|
112
|
+
inside->mirror = true;
|
|
113
|
+
}
|
|
99
114
|
}
|
|
100
115
|
}
|
|
101
116
|
}
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
#include "Tile.h"
|
|
17
17
|
#include "Shape.h"
|
|
18
18
|
|
|
19
|
-
Polyline::Polyline(Tile* tile,
|
|
20
|
-
: raw_(polygon),
|
|
19
|
+
Polyline::Polyline(Tile* tile, std::vector<Point> polygon, const std::optional<RectBounds>& bounds)
|
|
20
|
+
: raw_(std::move(polygon)),
|
|
21
21
|
tile(tile)
|
|
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 {
|
|
@@ -32,25 +32,24 @@ Polyline::Polyline(Tile* tile, const std::vector<Point*>& polygon, const std::op
|
|
|
32
32
|
|
|
33
33
|
int Polyline::width() {
|
|
34
34
|
if (raw_.empty()) return 0;
|
|
35
|
-
return(
|
|
35
|
+
return(max_x_ - min_x);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
bool Polyline::boundary() {
|
|
39
|
-
return( tile->tg_border(Point{min_x, 0}) || tile->tg_border(Point{
|
|
39
|
+
return( tile->tg_border(Point{min_x, 0}) || tile->tg_border(Point{max_x_, 0}));
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
void Polyline::find_boundary() {
|
|
43
43
|
if (raw_.empty()) return;
|
|
44
44
|
min_x = std::numeric_limits<int>::max();
|
|
45
|
-
|
|
45
|
+
max_x_ = -std::numeric_limits<int>::max();
|
|
46
46
|
min_y_ = std::numeric_limits<int>::max();
|
|
47
47
|
max_y_ = -std::numeric_limits<int>::max();
|
|
48
|
-
for (Point
|
|
49
|
-
|
|
50
|
-
int
|
|
51
|
-
int y = p->y;
|
|
48
|
+
for (const Point& p : raw_) {
|
|
49
|
+
int x = p.x;
|
|
50
|
+
int y = p.y;
|
|
52
51
|
if (x < min_x) min_x = x;
|
|
53
|
-
if (x >
|
|
52
|
+
if (x > max_x_) max_x_ = x;
|
|
54
53
|
if (y < min_y_) min_y_ = y;
|
|
55
54
|
if (y > max_y_) max_y_ = y;
|
|
56
55
|
}
|
|
@@ -68,17 +67,17 @@ bool Polyline::vert_bounds_intersect(Bounds& vertical_bounds)
|
|
|
68
67
|
{ return !(this->max_y_ < vertical_bounds.min || vertical_bounds.max < this->min_y_);
|
|
69
68
|
}
|
|
70
69
|
|
|
71
|
-
bool Polyline::within(std::vector<Point
|
|
70
|
+
bool Polyline::within(std::vector<Point>& points) {
|
|
72
71
|
size_t n = points.size();
|
|
73
72
|
if (n < 3) return false;
|
|
74
|
-
const int tx = this->raw_[0]
|
|
75
|
-
const int ty = this->raw_[0]
|
|
73
|
+
const int tx = this->raw_[0].x;
|
|
74
|
+
const int ty = this->raw_[0].y;
|
|
76
75
|
bool inside = false;
|
|
77
76
|
for (size_t i = 0, j = n - 1; i < n; j = i++) {
|
|
78
|
-
const Point
|
|
79
|
-
const Point
|
|
80
|
-
if (((pi
|
|
81
|
-
(tx < (pj
|
|
77
|
+
const Point& pi = points[i];
|
|
78
|
+
const Point& pj = points[j];
|
|
79
|
+
if (((pi.y > ty) != (pj.y > ty)) &&
|
|
80
|
+
(tx < (pj.x - pi.x) * (ty - pi.y) / (pj.y - pi.y) + pi.x)) {
|
|
82
81
|
inside = !inside;
|
|
83
82
|
}
|
|
84
83
|
}
|
|
@@ -98,7 +97,7 @@ std::string Polyline::named() {
|
|
|
98
97
|
|
|
99
98
|
void Polyline::fill_bounds(RectBounds& target_bounds) const {
|
|
100
99
|
target_bounds.min_x = this->min_x;
|
|
101
|
-
target_bounds.max_x = this->
|
|
100
|
+
target_bounds.max_x = this->max_x_;
|
|
102
101
|
target_bounds.min_y = this->min_y_;
|
|
103
102
|
target_bounds.max_y = this->max_y_;
|
|
104
103
|
}
|
|
@@ -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,23 +40,24 @@ class Polyline : public Partitionable {
|
|
|
40
40
|
int width();
|
|
41
41
|
Tile *tile = nullptr;
|
|
42
42
|
Shape* shape = nullptr;
|
|
43
|
-
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_; }
|
|
47
|
+
const int max_x() const { return max_x_; }
|
|
47
48
|
void clear();
|
|
48
49
|
bool is_empty();
|
|
49
50
|
bool any_ancients = false;
|
|
50
51
|
bool vert_bounds_intersect(Bounds& vertical_bounds);
|
|
51
|
-
bool within(std::vector<Point
|
|
52
|
+
bool within(std::vector<Point>& points);
|
|
52
53
|
InnerPolyline* inside_inner_polyline = nullptr;
|
|
53
54
|
std::string named();
|
|
54
55
|
void set_named(std::string force_named) { this->named_ = force_named; }
|
|
55
56
|
void fill_bounds(RectBounds& target_bounds) const;
|
|
56
57
|
|
|
57
58
|
private:
|
|
58
|
-
std::vector<Point
|
|
59
|
-
int min_x,
|
|
59
|
+
std::vector<Point> raw_;
|
|
60
|
+
int min_x, max_x_, min_y_, max_y_;
|
|
60
61
|
void find_boundary();
|
|
61
62
|
uint32_t flags_ = 0;
|
|
62
63
|
std::string named_;
|
|
@@ -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
|
};
|
|
@@ -10,15 +10,29 @@
|
|
|
10
10
|
#include <vector>
|
|
11
11
|
#include "Shape.h"
|
|
12
12
|
#include "ShapePool.h"
|
|
13
|
+
#include "Tile.h"
|
|
13
14
|
|
|
14
15
|
Shape* ShapePool::acquire_shape(Polyline* outer_polyline, const std::vector<InnerPolyline*>& inner_polylines) {
|
|
15
|
-
shapes_storage.emplace_back(outer_polyline, inner_polylines);
|
|
16
|
+
shapes_storage.emplace_back(this, outer_polyline, inner_polylines);
|
|
16
17
|
Shape* shape = &shapes_storage.back();
|
|
18
|
+
this->shapes_count++;
|
|
17
19
|
return shape;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
void ShapePool::set_owner(Tile* tile) {
|
|
23
|
+
this->owner_tile_ = tile;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void ShapePool::detach_shape() {
|
|
27
|
+
this->shapes_count--;
|
|
28
|
+
if (this->shapes_count == 0) {
|
|
29
|
+
this->owner_tile_->unregister_pool(this);
|
|
30
|
+
delete this;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
InnerPolyline* ShapePool::acquire_inner_polyline(std::vector<Point> coords, Shape* shape) {
|
|
35
|
+
inner_polylines_storage.emplace_back(std::move(coords), shape);
|
|
22
36
|
InnerPolyline* ip = &inner_polylines_storage.back();
|
|
23
37
|
return ip;
|
|
24
38
|
}
|
|
@@ -35,8 +49,8 @@ Sequence* ShapePool::acquire_sequence() {
|
|
|
35
49
|
return s;
|
|
36
50
|
}
|
|
37
51
|
|
|
38
|
-
Polyline* ShapePool::acquire_polyline(Tile* tile,
|
|
39
|
-
polylines_storage.emplace_back(tile, polygon, bounds);
|
|
52
|
+
Polyline* ShapePool::acquire_polyline(Tile* tile, std::vector<Point> polygon, const std::optional<RectBounds>& bounds = std::nullopt) {
|
|
53
|
+
polylines_storage.emplace_back(tile, std::move(polygon), bounds);
|
|
40
54
|
Polyline* p = &polylines_storage.back();
|
|
41
55
|
return p;
|
|
42
56
|
}
|
|
@@ -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
|
};
|