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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/Gemfile.lock +1 -1
  4. data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +13 -27
  5. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.cpp +5 -7
  6. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.h +4 -1
  7. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.cpp +14 -15
  8. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.h +2 -4
  9. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Polygon.h +2 -2
  10. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.cpp +13 -12
  11. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +10 -58
  12. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.cpp +6 -6
  13. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.h +3 -2
  14. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.cpp +8 -13
  15. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/EndPoint.h +4 -4
  16. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.h +2 -0
  17. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/InnerPolyline.cpp +6 -6
  18. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/InnerPolyline.h +3 -3
  19. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Merger.cpp +4 -3
  20. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.cpp +59 -9
  21. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.h +6 -1
  22. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.cpp +48 -33
  23. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.h +4 -2
  24. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +13 -13
  25. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +4 -4
  26. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.cpp +2 -2
  27. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.h +1 -1
  28. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Queueable.h +4 -4
  29. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.cpp +7 -7
  30. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.h +2 -2
  31. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.cpp +8 -2
  32. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.h +4 -1
  33. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ShapePool.cpp +20 -5
  34. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ShapePool.h +6 -2
  35. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.cpp +8 -5
  36. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.cpp +9 -0
  37. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.h +1 -0
  38. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.cpp +4 -13
  39. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.h +1 -0
  40. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/LinearReducer.cpp +8 -8
  41. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/LinearReducer.h +2 -2
  42. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/Reducer.cpp +1 -1
  43. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/Reducer.h +2 -2
  44. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/UniqReducer.cpp +3 -3
  45. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/UniqReducer.h +1 -1
  46. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/VisvalingamReducer.cpp +3 -3
  47. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/VisvalingamReducer.h +10 -10
  48. data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +14 -14
  49. data/lib/contrek/bitmaps/chunky_bitmap.rb +11 -0
  50. data/lib/contrek/finder/concurrent/cluster.rb +1 -1
  51. data/lib/contrek/finder/concurrent/cursor.rb +0 -3
  52. data/lib/contrek/finder/concurrent/finder.rb +4 -0
  53. data/lib/contrek/finder/concurrent/merger.rb +1 -0
  54. data/lib/contrek/finder/concurrent/part.rb +36 -1
  55. data/lib/contrek/finder/concurrent/partitionable.rb +42 -23
  56. data/lib/contrek/finder/concurrent/vertical_merger.rb +4 -0
  57. data/lib/contrek/finder/polygon_finder.rb +2 -1
  58. data/lib/contrek/version.rb +1 -1
  59. metadata +5 -5
@@ -11,7 +11,7 @@
11
11
  #include <vector>
12
12
  #include "InnerPolyline.h"
13
13
 
14
- InnerPolyline::InnerPolyline(std::vector<Point*> raw_coordinates, Shape* shape)
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*>& InnerPolyline::raw() {
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]->y;
45
- int max_y = raw_coordinates_[0]->y;
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->y < min_y) min_y = pos->y;
48
- if (pos->y > max_y) max_y = pos->y;
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*> raw_coordinates, Shape* shape);
17
+ explicit InnerPolyline(std::vector<Point> raw_coordinates, Shape* shape);
18
18
  explicit InnerPolyline(Sequence* sequence);
19
- std::vector<Point*>& raw();
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*> raw_coordinates_;
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* p : polygon.outer) p->x += offset;
40
- for (const auto& seq : polygon.inner) {
41
- for (Point* p : seq) p->x += offset;
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 (*(pos->payload) == *(force_position->payload)) {
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* 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->y - this->head->payload->y;
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
- << " (" << std::to_string(static_cast<uint32_t>(type)) << ") (";
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->toString();
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* target = other_part.head->payload;
155
+ const Point& target = other_part.head->payload;
106
156
  QNode<Point>* cursor = this->tail;
107
157
 
108
158
  while (cursor != nullptr) {
109
- if (*cursor->payload == *target) {
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 (!(*s->payload == *o->payload)) {
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* 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)) new_part->orient();
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* position : polyline->raw())
46
- { if (polyline->tile->tg_border(*position))
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 == *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->trasmute_parts();
80
+ this->transmute_parts();
69
81
  }
70
82
 
71
- void Partitionable::trasmute_parts()
72
- { std::vector<Part*> insides;
73
- for (Part* p : parts_) {
74
- if (p->is(Part::SEAM)) insides.push_back(p);
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
- if (insides.size() < 2) return;
101
+ }
77
102
 
78
- for (Part* inside : insides)
79
- { for (Part* inside_compare : insides) {
80
- if (inside == inside_compare || !inside_compare->is(Part::SEAM) ) continue;
81
- int count = 0;
82
- inside->each([&](QNode<Point>* pos) -> bool {
83
- Position *position = static_cast<Position*>(pos);
84
- if (position->end_point()->queues_include(inside_compare))
85
- { count++;
86
- return true;
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 trasmute_parts();
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, const std::vector<Point*>& polygon, const std::optional<RectBounds>& bounds)
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* p : raw_) {
49
- if (!p) continue;
50
- int x = p->x;
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*>& points) {
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]->x;
75
- const int ty = this->raw_[0]->y;
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* 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)) {
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, const std::vector<Point*>& polygon, const std::optional<RectBounds>& bounds = std::nullopt);
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*>& raw() const { return raw_; }
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*>& points);
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*> raw_;
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* point)
16
+ Position::Position(Hub* hub, const Point& point)
17
17
  : QNode<Point>(point)
18
18
  { if (hub != nullptr) {
19
- int key = point->y;
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* 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* payload;
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* value) : payload(value) {}
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*> to_vector() const {
133
- std::vector<T*> out;
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->toString();
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->x;
26
+ int x0 = head->payload.x;
27
27
  this->rewind();
28
28
 
29
29
  while (QNode<Point>* position = this->iterator())
30
- { if (position->payload->x != x0) {
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]->y;
42
- int max_y = cache[0]->y;
41
+ int min_y = cache[0].y;
42
+ int max_y = cache[0].y;
43
43
  for (const auto& pos : cache) {
44
- if (pos->y < min_y) min_y = pos->y;
45
- if (pos->y > max_y) max_y = pos->y;
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*>& get_vector_cache() {
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*> vector_cache;
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
- InnerPolyline* ShapePool::acquire_inner_polyline(std::vector<Point*> coords, Shape* shape) {
21
- inner_polylines_storage.emplace_back(coords, shape);
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, const std::vector<Point*>& polygon, const std::optional<RectBounds>& bounds = std::nullopt) {
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*> coords, Shape* s);
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, const std::vector<Point*>& polygon, const std::optional<RectBounds>& bounds);
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
  };