contrek 1.1.9 → 1.2.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/CHANGELOG.md +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +11 -8
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.cpp +1 -2
- 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/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/lib/contrek/finder/concurrent/cluster.rb +1 -2
- data/lib/contrek/finder/concurrent/cursor.rb +56 -120
- data/lib/contrek/finder/concurrent/end_point.rb +2 -0
- 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
|
@@ -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);
|
|
@@ -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
|
|
@@ -39,74 +39,39 @@ module Contrek
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def join_inners!(outer_seq)
|
|
42
|
-
|
|
43
|
-
missing_shapes = []
|
|
44
|
-
@cluster.tiles.each do |tile|
|
|
45
|
-
tile.shapes.each do |shape|
|
|
46
|
-
next if shape.outer_polyline.on?(Polyline::TRACKED_OUTER) ||
|
|
47
|
-
shape.outer_polyline.on?(Polyline::TRACKED_INNER) ||
|
|
48
|
-
!shape.outer_polyline.boundary? ||
|
|
49
|
-
@shapes_sequence.include?(shape)
|
|
50
|
-
missing_shapes << shape
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
if missing_shapes.any?
|
|
55
|
-
to_delay_shapes = connect_missings(@shapes_sequence, missing_shapes)
|
|
56
|
-
if to_delay_shapes.any?
|
|
57
|
-
connect_missings(to_delay_shapes, missing_shapes)
|
|
58
|
-
while to_delay_shapes.any?
|
|
59
|
-
to_delay_shapes = connect_missings(@shapes_sequence, to_delay_shapes)
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
retme = collect_inner_sequences(outer_seq)
|
|
42
|
+
return_inner_polylines = []
|
|
65
43
|
|
|
66
|
-
@shapes_sequence.
|
|
67
|
-
shape.outer_polyline.turn_on(Polyline::TRACKED_INNER)
|
|
68
|
-
end
|
|
69
|
-
retme
|
|
70
|
-
end
|
|
44
|
+
@processing_shapes = @shapes_sequence.to_a
|
|
71
45
|
|
|
72
|
-
|
|
46
|
+
@processing_shapes.each do |shape|
|
|
47
|
+
polyline = shape.outer_polyline
|
|
48
|
+
polyline.parts.each do |part|
|
|
49
|
+
if part.innerable?
|
|
50
|
+
all_parts = []
|
|
51
|
+
bounds = {min: polyline.max_y, max: 0}
|
|
52
|
+
traverse_inner(part, all_parts, bounds)
|
|
53
|
+
range_of_bounds = (bounds[:min]..bounds[:max])
|
|
73
54
|
|
|
74
|
-
|
|
75
|
-
|
|
55
|
+
retme_sequence = Sequence.new
|
|
56
|
+
all_parts.each do |part|
|
|
57
|
+
part.touch!
|
|
58
|
+
retme_sequence.move_from(part) do |position|
|
|
59
|
+
next false if part.is?(Part::ADDED) && !(range_of_bounds === position.payload[:y])
|
|
76
60
|
|
|
77
|
-
|
|
78
|
-
polyline = shape.outer_polyline
|
|
79
|
-
missing_shapes.each do |missing_shape|
|
|
80
|
-
missing_outer_polyline = missing_shape.outer_polyline
|
|
81
|
-
next if (polyline.mixed_tile_origin == false && missing_outer_polyline.tile == polyline.tile) || # accepts only other side ones
|
|
82
|
-
missing_outer_polyline.on?(Polyline::TRACKED_OUTER) ||
|
|
83
|
-
polyline == missing_outer_polyline ||
|
|
84
|
-
!polyline.vert_intersect?(missing_outer_polyline)
|
|
85
|
-
|
|
86
|
-
if (intersection = polyline.intersection(missing_outer_polyline)).any?
|
|
87
|
-
inject_sequences_left, inject_sequences_right = polyline.sew!(intersection, missing_outer_polyline)
|
|
88
|
-
if inject_sequences_left.nil?
|
|
89
|
-
delay_shapes << missing_shape
|
|
90
|
-
next
|
|
91
|
-
end
|
|
92
|
-
combine!(inject_sequences_right, inject_sequences_left).each do |sewn_sequence|
|
|
93
|
-
sewn_sequence.uniq!
|
|
94
|
-
if sewn_sequence.size > 1 && sewn_sequence.map { |c| c[:x] }.uniq.size > 1 # only areas
|
|
95
|
-
@orphan_inners << InnerPolyline.new(shape: shape, raw_coordinates: sewn_sequence, recombined: true)
|
|
61
|
+
!(polyline.tile.tg_border?(position.payload) && position.end_point.tracked_outer)
|
|
96
62
|
end
|
|
97
63
|
end
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
missing_outer_polyline.turn_on(Polyline::TRACKED_INNER)
|
|
102
|
-
@orphan_inners += missing_shape.inner_polylines
|
|
64
|
+
if retme_sequence.is_not_vertical
|
|
65
|
+
return_inner_polylines << InnerPolyline.new(sequence: retme_sequence)
|
|
66
|
+
end
|
|
103
67
|
end
|
|
104
68
|
end
|
|
105
69
|
end
|
|
106
|
-
|
|
107
|
-
delay_shapes
|
|
70
|
+
return_inner_polylines
|
|
108
71
|
end
|
|
109
72
|
|
|
73
|
+
private
|
|
74
|
+
|
|
110
75
|
# rubocop:disable Lint/NonLocalExitFromIterator
|
|
111
76
|
def traverse_outer(act_part, all_parts, shapes_sequence, outer_joined_polyline)
|
|
112
77
|
last_part = all_parts.last
|
|
@@ -126,13 +91,19 @@ module Contrek
|
|
|
126
91
|
outer_joined_polyline.head.payload == new_position.payload &&
|
|
127
92
|
act_part == all_parts.first
|
|
128
93
|
outer_joined_polyline.add(Position.new(position: new_position.payload, hub: @cluster.hub))
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
94
|
+
new_position.end_point.tracked_outer = true
|
|
95
|
+
versus = act_part.versus
|
|
96
|
+
part = new_position.end_point.queues.find do |p|
|
|
97
|
+
p.versus == -versus && p.polyline.tile != act_part.polyline.tile
|
|
98
|
+
end
|
|
99
|
+
if part
|
|
100
|
+
if all_parts[-2] != part
|
|
101
|
+
cont = true
|
|
102
|
+
if all_parts.size >= 2
|
|
103
|
+
map = all_parts[-2..].map(&:type).uniq
|
|
104
|
+
cont = false if map.size == 1 && map.first == Part::SEAM
|
|
105
|
+
end
|
|
106
|
+
if cont
|
|
136
107
|
shapes_sequence.add(part.polyline.shape)
|
|
137
108
|
part.next_position(new_position)
|
|
138
109
|
part.dead_end = true
|
|
@@ -149,36 +120,9 @@ module Contrek
|
|
|
149
120
|
traverse_outer(act_part.circular_next, all_parts, shapes_sequence, outer_joined_polyline)
|
|
150
121
|
end
|
|
151
122
|
|
|
152
|
-
def collect_inner_sequences(outer_seq)
|
|
153
|
-
return_inner_polylines = []
|
|
154
|
-
@shapes_sequence.each do |shape|
|
|
155
|
-
polyline = shape.outer_polyline
|
|
156
|
-
polyline.parts.each do |part|
|
|
157
|
-
if part.innerable?
|
|
158
|
-
all_parts = []
|
|
159
|
-
bounds = {min: polyline.max_y, max: 0}
|
|
160
|
-
traverse_inner(part, all_parts, bounds)
|
|
161
|
-
range_of_bounds = (bounds[:min]..bounds[:max])
|
|
162
|
-
|
|
163
|
-
retme_sequence = Sequence.new
|
|
164
|
-
all_parts.each do |part|
|
|
165
|
-
part.touch!
|
|
166
|
-
retme_sequence.move_from(part) do |position|
|
|
167
|
-
next false if part.is?(Part::ADDED) && !(range_of_bounds === position.payload[:y])
|
|
168
|
-
!(polyline.tile.tg_border?(position.payload) && position.end_point.queues.include?(outer_seq))
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
if retme_sequence.is_not_vertical
|
|
172
|
-
return_inner_polylines << InnerPolyline.new(sequence: retme_sequence)
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
return_inner_polylines
|
|
178
|
-
end
|
|
179
|
-
|
|
180
123
|
def traverse_inner(act_part, all_parts, bounds)
|
|
181
124
|
return if act_part == all_parts.first
|
|
125
|
+
|
|
182
126
|
if act_part.size > 0
|
|
183
127
|
min_y, max_y = act_part.to_a.minmax_by { |p| p[:y] }
|
|
184
128
|
bounds[:min] = [bounds[:min], min_y[:y]].min
|
|
@@ -186,26 +130,32 @@ module Contrek
|
|
|
186
130
|
end
|
|
187
131
|
if act_part.innerable?
|
|
188
132
|
all_parts << act_part
|
|
189
|
-
while (act_part = act_part.
|
|
133
|
+
while (act_part = act_part.circular_next)
|
|
190
134
|
if act_part.innerable?
|
|
191
135
|
all_parts << act_part
|
|
192
136
|
else
|
|
193
|
-
act_part.
|
|
194
|
-
|
|
195
|
-
|
|
137
|
+
if act_part.head
|
|
138
|
+
eligibles = act_part.head.end_point.queues.select { |p| p.polyline.tile != act_part.polyline.tile }
|
|
139
|
+
eligibles.each do |dest_part|
|
|
196
140
|
dest_part_versus = dest_part.versus
|
|
197
141
|
next if dest_part_versus != 0 && dest_part_versus == act_part.versus
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
end
|
|
205
|
-
all_parts << ins_part
|
|
142
|
+
|
|
143
|
+
link_seq = dest_part.continuum_to?(act_part)
|
|
144
|
+
if link_seq.any?
|
|
145
|
+
ins_part = Part.new(Part::ADDED, act_part.polyline)
|
|
146
|
+
link_seq.each do |pos|
|
|
147
|
+
ins_part.add(Position.new(position: nil, hub: nil, known_endpoint: pos))
|
|
206
148
|
end
|
|
207
|
-
|
|
208
|
-
|
|
149
|
+
all_parts << ins_part
|
|
150
|
+
end
|
|
151
|
+
shape = dest_part.polyline.shape
|
|
152
|
+
if !dest_part.polyline.on?(Polyline::TRACKED_OUTER)
|
|
153
|
+
@processing_shapes << shape
|
|
154
|
+
@orphan_inners += shape.inner_polylines
|
|
155
|
+
end
|
|
156
|
+
dest_part.polyline.turn_on(Polyline::TRACKED_OUTER)
|
|
157
|
+
if !dest_part.touched
|
|
158
|
+
dest_part.touch!
|
|
209
159
|
traverse_inner(dest_part.circular_next, all_parts, bounds)
|
|
210
160
|
return
|
|
211
161
|
end
|
|
@@ -219,20 +169,6 @@ module Contrek
|
|
|
219
169
|
end
|
|
220
170
|
end
|
|
221
171
|
# rubocop:enable Lint/NonLocalExitFromIterator
|
|
222
|
-
|
|
223
|
-
# example
|
|
224
|
-
# a = [[A],[B,C]]
|
|
225
|
-
# b = [[D],[E,F]]
|
|
226
|
-
# res = [[D,B,C],[E,F,A]]
|
|
227
|
-
def combine!(seqa, seqb)
|
|
228
|
-
rets = []
|
|
229
|
-
[seqa.count, seqb.count].min.times do
|
|
230
|
-
last = seqa.pop
|
|
231
|
-
first = seqb.shift
|
|
232
|
-
rets << first + last
|
|
233
|
-
end
|
|
234
|
-
rets
|
|
235
|
-
end
|
|
236
172
|
end
|
|
237
173
|
end
|
|
238
174
|
end
|
|
@@ -7,8 +7,8 @@ module Contrek
|
|
|
7
7
|
EXCLUSIVE = 0
|
|
8
8
|
ADDED = 2
|
|
9
9
|
|
|
10
|
-
attr_reader :polyline, :
|
|
11
|
-
attr_accessor :next, :circular_next, :prev, :type, :dead_end, :inverts, :trasmuted, :
|
|
10
|
+
attr_reader :polyline, :touched
|
|
11
|
+
attr_accessor :next, :circular_next, :prev, :type, :dead_end, :inverts, :trasmuted, :versus
|
|
12
12
|
def initialize(type, polyline)
|
|
13
13
|
@type = type
|
|
14
14
|
@polyline = polyline
|
|
@@ -19,7 +19,6 @@ module Contrek
|
|
|
19
19
|
@touched = false
|
|
20
20
|
@inverts = false
|
|
21
21
|
@trasmuted = false
|
|
22
|
-
@delayed = false
|
|
23
22
|
@versus = 0
|
|
24
23
|
end
|
|
25
24
|
|
|
@@ -27,10 +26,6 @@ module Contrek
|
|
|
27
26
|
@type == type
|
|
28
27
|
end
|
|
29
28
|
|
|
30
|
-
def set_polyline(polyline)
|
|
31
|
-
@polyline = polyline
|
|
32
|
-
end
|
|
33
|
-
|
|
34
29
|
def add_position(position)
|
|
35
30
|
hub = is?(EXCLUSIVE) ? nil : polyline.tile.cluster.hub
|
|
36
31
|
add(Position.new(position: position, hub: hub))
|
|
@@ -68,19 +63,6 @@ module Contrek
|
|
|
68
63
|
(@touched == false) && is?(EXCLUSIVE)
|
|
69
64
|
end
|
|
70
65
|
|
|
71
|
-
def intersect_part?(other_part)
|
|
72
|
-
intersect = false
|
|
73
|
-
other_part.each do |position|
|
|
74
|
-
if position.end_point.queues.include?(self)
|
|
75
|
-
intersect = true
|
|
76
|
-
false
|
|
77
|
-
else
|
|
78
|
-
true
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
intersect
|
|
82
|
-
end
|
|
83
|
-
|
|
84
66
|
def orient!
|
|
85
67
|
@versus = if size <= 1 || (size == 2 && @inverts)
|
|
86
68
|
0
|