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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.rubocop.yml +11 -0
  4. data/CHANGELOG.md +7 -1
  5. data/Gemfile +2 -0
  6. data/Gemfile.lock +1 -1
  7. data/README.md +1 -1
  8. data/Rakefile +2 -0
  9. data/contrek.gemspec +2 -0
  10. data/ext/cpp_polygon_finder/PolygonFinder/CMakeLists.txt +2 -4
  11. data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +118 -19
  12. data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.h +1 -0
  13. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.cpp +5 -7
  14. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.h +4 -1
  15. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.cpp +14 -15
  16. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.h +2 -4
  17. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Polygon.h +2 -2
  18. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.cpp +13 -13
  19. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +79 -354
  20. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.cpp +6 -6
  21. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.h +3 -2
  22. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.cpp +8 -8
  23. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/EndPoint.h +4 -4
  24. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.h +3 -1
  25. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/InnerPolyline.cpp +6 -6
  26. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/InnerPolyline.h +3 -3
  27. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Merger.cpp +4 -3
  28. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.cpp +29 -9
  29. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.h +3 -1
  30. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.cpp +45 -30
  31. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +18 -19
  32. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +6 -5
  33. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.cpp +2 -2
  34. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.h +1 -1
  35. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Queueable.h +4 -4
  36. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.cpp +7 -7
  37. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.h +2 -2
  38. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.cpp +8 -2
  39. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.h +4 -1
  40. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ShapePool.cpp +19 -5
  41. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ShapePool.h +6 -2
  42. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.cpp +117 -0
  43. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.h +41 -0
  44. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.cpp +9 -0
  45. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.h +1 -0
  46. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.cpp +4 -13
  47. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.h +1 -0
  48. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/LinearReducer.cpp +8 -8
  49. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/LinearReducer.h +2 -2
  50. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/Reducer.cpp +1 -1
  51. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/Reducer.h +2 -2
  52. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/UniqReducer.cpp +3 -3
  53. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/UniqReducer.h +1 -1
  54. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/VisvalingamReducer.cpp +3 -3
  55. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/VisvalingamReducer.h +10 -10
  56. data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +66 -16
  57. data/ext/cpp_polygon_finder/extconf.rb +2 -0
  58. data/lib/contrek/bitmaps/bitmap.rb +2 -0
  59. data/lib/contrek/bitmaps/chunky_bitmap.rb +13 -0
  60. data/lib/contrek/bitmaps/painting.rb +2 -0
  61. data/lib/contrek/bitmaps/png_bitmap.rb +2 -0
  62. data/lib/contrek/bitmaps/raw_bitmap.rb +2 -0
  63. data/lib/contrek/bitmaps/rgb_color.rb +2 -0
  64. data/lib/contrek/bitmaps/rgb_cpp_color.rb +2 -0
  65. data/lib/contrek/bitmaps/sample_generator.rb +2 -0
  66. data/lib/contrek/cpp/cpp_concurrent_finder.rb +2 -0
  67. data/lib/contrek/cpp/cpp_concurrent_horizontal_merger.rb +2 -0
  68. data/lib/contrek/cpp/cpp_concurrent_merger.rb +2 -0
  69. data/lib/contrek/cpp/cpp_concurrent_streaming_merger.rb +11 -0
  70. data/lib/contrek/cpp/cpp_concurrent_vertical_merger.rb +2 -0
  71. data/lib/contrek/cpp/cpp_result.rb +2 -0
  72. data/lib/contrek/cpp/cpp_tempfile.rb +28 -0
  73. data/lib/contrek/finder/bounds.rb +2 -0
  74. data/lib/contrek/finder/concurrent/clipped_polygon_finder.rb +2 -0
  75. data/lib/contrek/finder/concurrent/cluster.rb +3 -1
  76. data/lib/contrek/finder/concurrent/cursor.rb +2 -0
  77. data/lib/contrek/finder/concurrent/end_point.rb +2 -0
  78. data/lib/contrek/finder/concurrent/fake_cluster.rb +2 -0
  79. data/lib/contrek/finder/concurrent/finder.rb +6 -0
  80. data/lib/contrek/finder/concurrent/horizontal_merger.rb +2 -0
  81. data/lib/contrek/finder/concurrent/hub.rb +2 -0
  82. data/lib/contrek/finder/concurrent/inner_polyline.rb +2 -0
  83. data/lib/contrek/finder/concurrent/listable.rb +2 -0
  84. data/lib/contrek/finder/concurrent/merger.rb +4 -0
  85. data/lib/contrek/finder/concurrent/part.rb +13 -0
  86. data/lib/contrek/finder/concurrent/partitionable.rb +33 -17
  87. data/lib/contrek/finder/concurrent/polyline.rb +2 -0
  88. data/lib/contrek/finder/concurrent/poolable.rb +2 -0
  89. data/lib/contrek/finder/concurrent/position.rb +2 -0
  90. data/lib/contrek/finder/concurrent/queueable.rb +2 -0
  91. data/lib/contrek/finder/concurrent/sequence.rb +2 -0
  92. data/lib/contrek/finder/concurrent/shape.rb +2 -0
  93. data/lib/contrek/finder/concurrent/streaming_merger.rb +89 -0
  94. data/lib/contrek/finder/concurrent/tile.rb +2 -0
  95. data/lib/contrek/finder/concurrent/vertical_merger.rb +8 -2
  96. data/lib/contrek/finder/list.rb +2 -0
  97. data/lib/contrek/finder/list_entry.rb +2 -0
  98. data/lib/contrek/finder/listable.rb +2 -0
  99. data/lib/contrek/finder/lists.rb +2 -0
  100. data/lib/contrek/finder/node.rb +2 -0
  101. data/lib/contrek/finder/node_cluster.rb +3 -1
  102. data/lib/contrek/finder/polygon_finder.rb +4 -1
  103. data/lib/contrek/finder/result.rb +2 -0
  104. data/lib/contrek/map/mercator_projection.rb +2 -0
  105. data/lib/contrek/matchers/matcher.rb +2 -0
  106. data/lib/contrek/matchers/matcher_hsb.rb +2 -0
  107. data/lib/contrek/matchers/value_not_matcher.rb +2 -0
  108. data/lib/contrek/reducers/linear_reducer.rb +2 -0
  109. data/lib/contrek/reducers/reducer.rb +2 -0
  110. data/lib/contrek/reducers/uniq_reducer.rb +2 -0
  111. data/lib/contrek/reducers/visvalingam_reducer.rb +2 -0
  112. data/lib/contrek/shared/result.rb +2 -0
  113. data/lib/contrek/version.rb +3 -1
  114. data/lib/contrek.rb +5 -0
  115. metadata +11 -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,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
- << " (" << std::to_string(static_cast<uint32_t>(type)) << ") (";
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->toString();
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* target = other_part.head->payload;
125
+ const Point& target = other_part.head->payload;
106
126
  QNode<Point>* cursor = this->tail;
107
127
 
108
128
  while (cursor != nullptr) {
109
- if (*cursor->payload == *target) {
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 (!(*s->payload == *o->payload)) {
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* 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* position : polyline->raw())
46
- { if (polyline->tile->tg_border(*position))
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 == *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
- { std::vector<Part*> insides;
73
- for (Part* p : parts_) {
74
- if (p->is(Part::SEAM)) insides.push_back(p);
75
- }
76
- if (insides.size() < 2) return;
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
- 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;
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
- 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;
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, const std::vector<Point*>& polygon, const std::optional<RectBounds>& bounds)
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
- max_x = bounds->max_x;
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(max_x - min_x);
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{max_x, 0}));
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
- max_x = -std::numeric_limits<int>::max();
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* p : raw_) {
49
- if (!p) continue;
50
- int x = p->x;
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 > max_x) max_x = 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*>& points) {
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]->x;
75
- const int ty = this->raw_[0]->y;
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* 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)) {
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->max_x;
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, 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,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*> 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_; }
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*>& points);
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*> raw_;
59
- int min_x, max_x, min_y_, max_y_;
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* 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
  };
@@ -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
- InnerPolyline* ShapePool::acquire_inner_polyline(std::vector<Point*> coords, Shape* shape) {
21
- inner_polylines_storage.emplace_back(coords, shape);
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, const std::vector<Point*>& polygon, const std::optional<RectBounds>& bounds = std::nullopt) {
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*> 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
  };