contrek 1.1.8 → 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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -1
  3. data/Gemfile.lock +1 -1
  4. data/README.md +11 -8
  5. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.cpp +0 -2
  6. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.cpp +1 -2
  7. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.cpp +66 -185
  8. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.h +0 -3
  9. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/EndPoint.h +4 -2
  10. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.cpp +38 -36
  11. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.h +2 -5
  12. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.cpp +0 -128
  13. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.h +0 -6
  14. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +0 -50
  15. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +2 -8
  16. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.cpp +22 -3
  17. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Queueable.h +1 -57
  18. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.cpp +0 -12
  19. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.h +0 -3
  20. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.cpp +11 -3
  21. data/lib/contrek/finder/concurrent/cluster.rb +1 -2
  22. data/lib/contrek/finder/concurrent/cursor.rb +55 -131
  23. data/lib/contrek/finder/concurrent/end_point.rb +2 -0
  24. data/lib/contrek/finder/concurrent/part.rb +28 -32
  25. data/lib/contrek/finder/concurrent/partitionable.rb +0 -81
  26. data/lib/contrek/finder/concurrent/polyline.rb +3 -47
  27. data/lib/contrek/finder/concurrent/position.rb +8 -2
  28. data/lib/contrek/finder/concurrent/queueable.rb +0 -58
  29. data/lib/contrek/finder/concurrent/tile.rb +0 -4
  30. data/lib/contrek/finder/concurrent/vertical_merger.rb +9 -5
  31. data/lib/contrek/version.rb +1 -1
  32. metadata +3 -3
  33. /data/{LICENSE-MIT.md → lib/LICENSE-MIT.md} +0 -0
@@ -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
- void reset_tracked_endpoints();
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) this->end_point_->queues().erase(q);
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) this->end_point_->queues().insert(q);
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
- if (p) std::swap(p->x, p->y);
49
+ process_p(p);
42
50
  }
43
51
  for (auto& sequence : polygon.inner) {
44
52
  for (Point* p : sequence) {
45
- if (p) std::swap(p->x, p->y);
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.boundary? && shape.outer_polyline.next_tile_eligible_shapes.any?
46
+ if shape.outer_polyline.any_ancients
48
47
  cursor = Cursor.new(cluster: self, shape: shape)
49
48
 
50
49
  new_outer = nil