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
@@ -32,6 +32,7 @@ void StreamingMerger::add_tile(ProcessResult& result, bool flush)
32
32
  this->process_tiles();
33
33
  this->tiles_.queue_push(this->whole_tile);
34
34
  this->stream_polygons(this->whole_tile, flush);
35
+ this->whole_tile->shapes().shrink_to_fit();
35
36
  }
36
37
  }
37
38
 
@@ -45,16 +46,18 @@ void StreamingMerger::stream_polygons(Tile* tile, bool flush) {
45
46
  ensure_header();
46
47
  if (int tile_end_x = tile->end_x(); true) {
47
48
  tile->shapes().erase(
48
- std::remove_if(tile->shapes().begin(), tile->shapes().end(), [this, flush, tile_end_x](const Shape* shape) {
49
+ std::remove_if(tile->shapes().begin(), tile->shapes().end(), [this, flush, tile_end_x](Shape* shape) {
49
50
  if (flush || shape->outer_polyline->max_x() < (tile_end_x - 1)) {
50
51
  this->moved++;
51
52
  this->stream_raw_polygon(shape);
53
+ shape->detach_from_pool();
52
54
  return true;
53
55
  }
54
56
  return false;
55
57
  }),
56
58
  tile->shapes().end());
57
59
  }
60
+ stream->flush();
58
61
  if (flush) {
59
62
  ensure_footer();
60
63
  }
@@ -62,18 +65,18 @@ void StreamingMerger::stream_polygons(Tile* tile, bool flush) {
62
65
 
63
66
  void StreamingMerger::stream_raw_polygon(const Shape* shape) {
64
67
  std::ostringstream outer_oss;
65
- const std::vector<Point*> points = shape->outer_polyline->raw();
68
+ const std::vector<Point>& points = shape->outer_polyline->raw();
66
69
  for (size_t i = 0; i < points.size(); ++i) {
67
- outer_oss << points[i]->y << "," << points[i]->x;
70
+ outer_oss << points[i].y << "," << points[i].x;
68
71
  if (i < points.size() - 1) outer_oss << " ";
69
72
  }
70
73
  *stream << svg_outer_polygon_string(outer_oss.str());
71
74
 
72
75
  for (const auto& inner_polyline : shape->inner_polylines) {
73
76
  std::ostringstream inner_oss;
74
- const std::vector<Point*> inner_points = inner_polyline->raw();
77
+ const std::vector<Point>& inner_points = inner_polyline->raw();
75
78
  for (size_t i = 0; i < inner_points.size(); ++i) {
76
- inner_oss << inner_points[i]->y << "," << inner_points[i]->x;
79
+ inner_oss << inner_points[i].y << "," << inner_points[i].x;
77
80
  if (i < inner_points.size() - 1) inner_oss << " ";
78
81
  }
79
82
  *stream << svg_inner_polygon_string(inner_oss.str());
@@ -27,6 +27,7 @@ Tile::Tile(Finder *finder, int start_x, int end_x, std::string name, const Bench
27
27
  name_(name),
28
28
  benchmarks(b) {
29
29
  this->shapes_pool = new ShapePool();
30
+ this->shapes_pool->set_owner(this);
30
31
  this->shapes_pools.push_back(this->shapes_pool);
31
32
  }
32
33
 
@@ -156,6 +157,14 @@ std::vector<std::pair<int, int>> Tile::compute_treemap()
156
157
  void Tile::adopt(Tile* other) {
157
158
  for (ShapePool* pool : other->shapes_pools) {
158
159
  this->shapes_pools.push_back(pool);
160
+ pool->set_owner(this);
159
161
  }
160
162
  other->shapes_pools.clear();
161
163
  }
164
+
165
+ void Tile::unregister_pool(ShapePool* shape_pool) {
166
+ auto it = std::find(this->shapes_pools.begin(), this->shapes_pools.end(), shape_pool);
167
+ if (it != this->shapes_pools.end()) {
168
+ this->shapes_pools.erase(it);
169
+ }
170
+ }
@@ -59,4 +59,5 @@ class Tile {
59
59
  std::vector<ShapePool*> shapes_pools;
60
60
  ShapePool* shapes_pool;
61
61
  void adopt(Tile* other);
62
+ void unregister_pool(ShapePool* shape_pool);
62
63
  };
@@ -12,7 +12,6 @@
12
12
  #include <vector>
13
13
  #include <algorithm>
14
14
  #include <utility>
15
- #include <unordered_set>
16
15
  #include "VerticalMerger.h"
17
16
 
18
17
  VerticalMerger::VerticalMerger(int number_of_threads, std::vector<std::string> *options)
@@ -36,21 +35,13 @@ ProcessResult* VerticalMerger::process_info() {
36
35
 
37
36
  void VerticalMerger::transpose(ProcessResult& result) {
38
37
  std::swap(result.width, result.height);
39
- std::unordered_set<Point*> seen;
40
38
  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
- };
48
- for (Point* p : polygon.outer) {
49
- process_p(p);
39
+ for (Point& p : polygon.outer) {
40
+ std::swap(p.x, p.y);
50
41
  }
51
42
  for (auto& sequence : polygon.inner) {
52
- for (Point* p : sequence) {
53
- process_p(p);
43
+ for (Point& p : sequence) {
44
+ std::swap(p.x, p.y);
54
45
  }
55
46
  }
56
47
  std::swap(polygon.bounds.min_x, polygon.bounds.min_y);
@@ -17,6 +17,7 @@ class VerticalMerger : public Merger {
17
17
  VerticalMerger(int number_of_threads, std::vector<std::string> *options);
18
18
  void add_tile(ProcessResult& result) override;
19
19
  ProcessResult* process_info() override;
20
+ bool transpose() const override { return true; };
20
21
 
21
22
  private:
22
23
  void transpose(ProcessResult& result);
@@ -14,23 +14,23 @@
14
14
  #include "LinearReducer.h"
15
15
  #include "Reducer.h"
16
16
 
17
- LinearReducer::LinearReducer(std::vector<Point*> &list_of_points)
17
+ LinearReducer::LinearReducer(std::vector<Point>& list_of_points)
18
18
  : Reducer(list_of_points) {
19
19
  }
20
20
 
21
21
  void LinearReducer::reduce() {
22
22
  if (points.size() < 2) return;
23
23
 
24
- Point* start_p = points[0];
25
- Point* end_p = points[1];
24
+ Point start_p = points[0];
25
+ Point end_p = points[1];
26
26
  auto dir = seq_dir(start_p, end_p);
27
27
 
28
28
  for (size_t i = 2; i < points.size(); ++i) {
29
- Point* point = points[i];
29
+ Point point = points[i];
30
30
  auto act_seq = seq_dir(end_p, point);
31
31
  if (act_seq == dir) {
32
- auto it = std::find_if(points.begin(), points.end(), [&](Point* p) { // TODO(ema): optimize...
33
- return p->x == end_p->x && p->y == end_p->y;
32
+ auto it = std::find_if(points.begin(), points.end(), [&](const Point& p) { // TODO(ema): optimize...
33
+ return p.x == end_p.x && p.y == end_p.y;
34
34
  });
35
35
  if (it != points.end()) {
36
36
  size_t removed_idx = std::distance(points.begin(), it);
@@ -44,6 +44,6 @@ void LinearReducer::reduce() {
44
44
  }
45
45
  }
46
46
 
47
- std::array<int, 2> LinearReducer::seq_dir(Point *a, Point *b)
48
- { return { b->x - a->x, b->y - a->y };
47
+ std::array<int, 2> LinearReducer::seq_dir(const Point& a, const Point& b)
48
+ { return { b.x - a.x, b.y - a.y };
49
49
  }
@@ -14,9 +14,9 @@
14
14
 
15
15
  class LinearReducer : public Reducer {
16
16
  public:
17
- explicit LinearReducer(std::vector<Point*>& list_of_points);
17
+ explicit LinearReducer(std::vector<Point>& list_of_points);
18
18
  void reduce();
19
19
 
20
20
  private:
21
- std::array<int, 2> seq_dir(Point *a, Point *b);
21
+ std::array<int, 2> seq_dir(const Point& a, const Point& b);
22
22
  };
@@ -9,7 +9,7 @@
9
9
 
10
10
  #include "Reducer.h"
11
11
 
12
- Reducer::Reducer(std::vector<Point*>& list_of_points)
12
+ Reducer::Reducer(std::vector<Point>& list_of_points)
13
13
  : points(list_of_points) {
14
14
  }
15
15
 
@@ -15,8 +15,8 @@
15
15
  struct Point;
16
16
  class Reducer {
17
17
  public:
18
- explicit Reducer(std::vector<Point*>& list_of_points);
18
+ explicit Reducer(std::vector<Point>& list_of_points);
19
19
  virtual void reduce();
20
20
  protected:
21
- std::vector<Point*> &points;
21
+ std::vector<Point> &points;
22
22
  };
@@ -13,12 +13,12 @@
13
13
  #include "UniqReducer.h"
14
14
  #include "Reducer.h"
15
15
 
16
- UniqReducer::UniqReducer(std::vector<Point*>& list_of_points) : Reducer(list_of_points) {
16
+ UniqReducer::UniqReducer(std::vector<Point>& list_of_points) : Reducer(list_of_points) {
17
17
  }
18
18
 
19
19
  struct is_near {
20
- bool operator() (Point* first, Point* second) const {
21
- return first->x == second->x && first->y == second->y;
20
+ bool operator() (const Point& first, const Point& second) const {
21
+ return first.x == second.x && first.y == second.y;
22
22
  }
23
23
  };
24
24
 
@@ -13,6 +13,6 @@
13
13
 
14
14
  class UniqReducer : public Reducer {
15
15
  public:
16
- explicit UniqReducer(std::vector<Point*>& list_of_points);
16
+ explicit UniqReducer(std::vector<Point>& list_of_points);
17
17
  void reduce();
18
18
  };
@@ -10,7 +10,7 @@
10
10
  #include <vector>
11
11
  #include "VisvalingamReducer.h"
12
12
 
13
- VisvalingamReducer::VisvalingamReducer(std::vector<Point*>& list_of_points, float tolerance)
13
+ VisvalingamReducer::VisvalingamReducer(std::vector<Point>& list_of_points, float tolerance)
14
14
  : Reducer(list_of_points) {
15
15
  this->tolerance = tolerance * tolerance;
16
16
  }
@@ -18,11 +18,11 @@ VisvalingamReducer::VisvalingamReducer(std::vector<Point*>& list_of_points, floa
18
18
  VisvalingamReducer::~VisvalingamReducer() {}
19
19
 
20
20
  void VisvalingamReducer::reduce() {
21
- std::vector<Point*> new_points = this->simplify();
21
+ std::vector<Point> new_points = this->simplify();
22
22
  points.assign(new_points.begin(), new_points.end());
23
23
  }
24
24
 
25
- std::vector<Point*> VisvalingamReducer::simplify() {
25
+ std::vector<Point> VisvalingamReducer::simplify() {
26
26
  Vertex* vwLine = Vertex::buildLine(points);
27
27
  float minArea = this->tolerance;
28
28
  for (;;) {
@@ -17,21 +17,21 @@ struct Point;
17
17
 
18
18
  class VisvalingamReducer : public Reducer {
19
19
  public:
20
- VisvalingamReducer(std::vector<Point*>& list_of_points, float tolerance);
20
+ VisvalingamReducer(std::vector<Point>& list_of_points, float tolerance);
21
21
  virtual ~VisvalingamReducer();
22
22
  void reduce();
23
- std::vector<Point*> simplify();
23
+ std::vector<Point> simplify();
24
24
 
25
25
  class Triangle {
26
26
  public:
27
- static int area(Point* a, Point* b, Point* c) {
28
- return std::abs(((c->x - a->x) * (b->y - a->y) - (b->x - a->x) * (c->y - a->y)) / 2);
27
+ static int area(const Point& a, const Point& b, const Point& c) {
28
+ return std::abs(((c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y)) / 2);
29
29
  }
30
30
  };
31
31
 
32
32
  class Vertex {
33
33
  const float MAX_AREA = std::numeric_limits<float>::max();
34
- explicit Vertex(Point* pt) {
34
+ explicit Vertex(const Point& pt) {
35
35
  this->pt = pt;
36
36
  this->prev = nullptr;
37
37
  this->next = nullptr;
@@ -40,7 +40,7 @@ class VisvalingamReducer : public Reducer {
40
40
  }
41
41
 
42
42
  public:
43
- Point* pt;
43
+ Point pt;
44
44
  void setNext(Vertex* nextp) { this->next = nextp; }
45
45
  void setPrec(Vertex* prev) { this->prev = prev; }
46
46
  void updateArea() {
@@ -54,10 +54,10 @@ class VisvalingamReducer : public Reducer {
54
54
  Vertex* get_next() { return this->next; }
55
55
  bool isLiving() { return this->isLive; }
56
56
 
57
- static Vertex* buildLine(std::vector<Point*>& pts) {
57
+ static Vertex* buildLine(std::vector<Point>& pts) {
58
58
  Vertex* first = nullptr;
59
59
  Vertex* prev = nullptr;
60
- for (Point* p : pts) {
60
+ for (const Point& p : pts) {
61
61
  Vertex* v = new Vertex(p);
62
62
  if (!first) first = v;
63
63
  v->setPrec(prev);
@@ -88,8 +88,8 @@ class VisvalingamReducer : public Reducer {
88
88
  return result;
89
89
  }
90
90
 
91
- static std::vector<Point*> getCoordinates(Vertex* head) {
92
- std::vector<Point*> coords;
91
+ static std::vector<Point> getCoordinates(Vertex* head) {
92
+ std::vector<Point> coords;
93
93
  Vertex* curr = head;
94
94
  while (curr) {
95
95
  coords.push_back(curr->pt);
@@ -27,8 +27,6 @@
27
27
  #include "PolygonFinder/src/polygon/finder/List.h"
28
28
  #include "PolygonFinder/src/polygon/finder/Lists.cpp"
29
29
  #include "PolygonFinder/src/polygon/finder/Lists.h"
30
- #include "PolygonFinder/src/polygon/finder/PointPool.h"
31
- #include "PolygonFinder/src/polygon/finder/PointPool.cpp"
32
30
  #include "PolygonFinder/src/polygon/finder/Polygon.h"
33
31
  #include "PolygonFinder/src/polygon/bitmaps/Bitmap.h"
34
32
  #include "PolygonFinder/src/polygon/bitmaps/Bitmap.cpp"
@@ -186,24 +184,25 @@ class To_Ruby<ProcessResult*>
186
184
  return_me[Symbol("named_sequence")] = pr->named_sequence;
187
185
  return_me[Symbol("width")] = pr->width;
188
186
  return_me[Symbol("height")] = pr->height;
187
+ return_me[Symbol("versus")] = Symbol(pr->versus == Node::O ? "o" : "a");
189
188
 
190
189
  Rice::Array out;
191
190
  for (Polygon& x : pr->polygons)
192
191
  { Rice::Hash poly_hash = Rice::Hash();
193
- // OUTER: std::vector<Point*>
192
+ // OUTER: std::vector<Point>
194
193
  Rice::Array outer_flat;
195
- for (Point* p : x.outer) {
196
- outer_flat.push(p->x);
197
- outer_flat.push(p->y);
194
+ for (const Point& p : x.outer) {
195
+ outer_flat.push(p.x);
196
+ outer_flat.push(p.y);
198
197
  }
199
198
  poly_hash[Symbol("outer")] = outer_flat;
200
- // INNER: std::list<std::vector<Point*>>
199
+ // INNER: std::list<std::vector<Point>>
201
200
  Rice::Array inner_collection;
202
- for (const std::vector<Point*>& sequence : x.inner) {
201
+ for (const std::vector<Point>& sequence : x.inner) {
203
202
  Rice::Array sequence_flat;
204
- for (Point* p : sequence) {
205
- sequence_flat.push(p->x);
206
- sequence_flat.push(p->y);
203
+ for (const Point& p : sequence) {
204
+ sequence_flat.push(p.x);
205
+ sequence_flat.push(p.y);
207
206
  }
208
207
  inner_collection.push(sequence_flat);
209
208
  }
@@ -251,6 +250,7 @@ ProcessResult ruby_result_to_process_result(Rice::Object rb_result) {
251
250
  Rice::Hash metadata = rb_result.iv_get("@metadata_storage");
252
251
  pr.width = detail::From_Ruby<int>().convert(metadata[Symbol("width")].value());
253
252
  pr.height = detail::From_Ruby<int>().convert(metadata[Symbol("height")].value());
253
+ pr.versus = metadata[Symbol("versus")] == Symbol("o") ? Node::O : Node::A;
254
254
 
255
255
  Rice::Array rb_polygons = rb_result.iv_get("@polygons_storage");
256
256
  for (size_t i = 0; i < rb_polygons.size(); ++i) {
@@ -270,17 +270,17 @@ ProcessResult ruby_result_to_process_result(Rice::Object rb_result) {
270
270
  for (size_t j = 0; j < outer_flat.size(); j += 2) {
271
271
  int px = detail::From_Ruby<int>().convert(outer_flat[j].value());
272
272
  int py = detail::From_Ruby<int>().convert(outer_flat[j+1].value());
273
- poly.outer.push_back(new Point(px, py));
273
+ poly.outer.push_back(Point(px, py));
274
274
  }
275
275
  // INNER
276
276
  Rice::Array inner_collection = (Rice::Array)rb_poly[Symbol("inner")];
277
277
  for (size_t j = 0; j < inner_collection.size(); ++j) {
278
278
  Rice::Array sequence_flat = (Rice::Array)inner_collection[j];
279
- std::vector<Point*> hole;
279
+ std::vector<Point> hole;
280
280
  for (size_t k = 0; k < sequence_flat.size(); k += 2) {
281
281
  int px = detail::From_Ruby<int>().convert(sequence_flat[k].value());
282
282
  int py = detail::From_Ruby<int>().convert(sequence_flat[k+1].value());
283
- hole.push_back(new Point(px, py));
283
+ hole.push_back(Point(px, py));
284
284
  }
285
285
  poly.inner.push_back(hole);
286
286
  }
@@ -89,6 +89,17 @@ module Contrek
89
89
  puts
90
90
  end
91
91
 
92
+ def transpose!
93
+ transposed = ""
94
+ w.times do |x|
95
+ h.times do |y|
96
+ transposed += value_at(x, y)
97
+ end
98
+ end
99
+ @raw = transposed
100
+ @module = h
101
+ end
102
+
92
103
  private
93
104
 
94
105
  def next_color(color)
@@ -3,7 +3,7 @@
3
3
  module Contrek
4
4
  module Concurrent
5
5
  class Cluster
6
- attr_reader :tiles, :hub
6
+ attr_reader :tiles, :hub, :finder
7
7
 
8
8
  def initialize(finder:, height:, start_x:, end_x:)
9
9
  @finder = finder
@@ -102,9 +102,6 @@ module Contrek
102
102
  if act_part.is?(Part::EXCLUSIVE)
103
103
  return if act_part.size == 0
104
104
  while (position = act_part.next_position)
105
- return if outer_joined_polyline.size > 1 &&
106
- outer_joined_polyline.head.payload == position.payload &&
107
- act_part == all_parts.first
108
105
  outer_joined_polyline.add(position)
109
106
  end
110
107
  else
@@ -99,6 +99,10 @@ module Contrek
99
99
  Contrek::Finder::Result.new(raw_polygons, metadata)
100
100
  end
101
101
 
102
+ def transpose?
103
+ false
104
+ end
105
+
102
106
  private
103
107
 
104
108
  def process_tiles!(bitmap, height:)
@@ -16,6 +16,7 @@ module Contrek
16
16
 
17
17
  def add_tile(result)
18
18
  @height ||= result.metadata[:height]
19
+ @options[:versus] ||= result.metadata[:versus]
19
20
  end_x = @current_x + result.metadata[:width]
20
21
 
21
22
  tile = Tile.new(
@@ -10,11 +10,13 @@ module Contrek
10
10
  ADDED = 2
11
11
 
12
12
  attr_reader :polyline, :touched
13
- attr_accessor :next, :circular_next, :prev, :type, :dead_end, :inverts, :trasmuted, :versus, :mirror
13
+ attr_accessor :next, :circular_next, :prev, :type, :dead_end, :inverts,
14
+ :trasmuted, :versus, :mirror, :next_seam, :transmutation_skip
14
15
  def initialize(type, polyline)
15
16
  @type = type
16
17
  @polyline = polyline
17
18
  @next = nil
19
+ @next_seam = nil
18
20
  @circular_next = nil
19
21
  @prev = nil
20
22
  @dead_end = false
@@ -23,6 +25,7 @@ module Contrek
23
25
  @trasmuted = false
24
26
  @versus = 0
25
27
  @mirror = false
28
+ @transmutation_skip = false
26
29
  end
27
30
 
28
31
  def is?(type)
@@ -80,6 +83,38 @@ module Contrek
80
83
  end
81
84
  end
82
85
 
86
+ def try_transmutation!
87
+ head_queues = head.end_point.queues
88
+ return if head_queues.size == 1
89
+ other_head_part = head_queues.find { |part| part.polyline.tile == polyline.tile && part != self }
90
+ if other_head_part
91
+ tail_queues = tail.end_point.queues
92
+ if tail_queues.find { |part| part == other_head_part }
93
+ if (other_head_part.tail.payload[:y] == tail.payload[:y] && other_head_part.head.payload[:y] == head.payload[:y]) ||
94
+ (other_head_part.tail.payload[:y] == head.payload[:y] && other_head_part.head.payload[:y] == tail.payload[:y])
95
+ if self.next.nil? && other_head_part.prev.nil?
96
+ self.mirror = true
97
+ end
98
+ else
99
+ self.type = Part::EXCLUSIVE
100
+ self.trasmuted = true
101
+ other_head_part.transmutation_skip = true
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ def within?(other)
108
+ self_min, self_max = [head.payload[:y], tail.payload[:y]].minmax
109
+ other_min, other_max = [other.head.payload[:y], other.tail.payload[:y]].minmax
110
+ self_min >= other_min && self_max <= other_max
111
+ end
112
+
113
+ def same_length?(other)
114
+ (head.payload[:y] - tail.payload[:y]).abs ==
115
+ (other.head.payload[:y] - other.tail.payload[:y]).abs
116
+ end
117
+
83
118
  def continuum_to?(other)
84
119
  return [] if size <= 2 && inverts && other.size <= 2 && other.inverts
85
120
  return [] if other.head.nil?
@@ -8,6 +8,8 @@ module Contrek
8
8
  def initialize(*args, **kwargs, &block)
9
9
  super
10
10
  @parts = []
11
+ @first_seam = nil
12
+ @last_seam = nil
11
13
  end
12
14
 
13
15
  def add_part(new_part)
@@ -16,8 +18,14 @@ module Contrek
16
18
  last.next = last.circular_next = new_part if last
17
19
  new_part.circular_next = @parts.first
18
20
  new_part.prev = last
19
-
20
- new_part.orient! if new_part.is?(Part::SEAM)
21
+ if new_part.is?(Part::SEAM)
22
+ @first_seam ||= new_part
23
+ if !@last_seam.nil?
24
+ @last_seam.next_seam = new_part
25
+ end
26
+ @last_seam = new_part
27
+ new_part.orient!
28
+ end
21
29
  end
22
30
 
23
31
  def inspect_parts
@@ -27,6 +35,8 @@ module Contrek
27
35
  def partition!
28
36
  current_part = nil
29
37
  @parts = []
38
+ @first_seam = nil
39
+ @last_seam = nil
30
40
 
31
41
  @raw.each_with_index do |position, n|
32
42
  if @tile.tg_border?(position)
@@ -49,7 +59,7 @@ module Contrek
49
59
  end
50
60
  add_part(current_part)
51
61
 
52
- trasmute_parts!
62
+ transmute_parts!
53
63
  end
54
64
 
55
65
  private
@@ -57,28 +67,37 @@ module Contrek
57
67
  # If there are SEAM parts and one is canceled out by another within the same polyline,
58
68
  # meaning that all its points are repeated in another, longer sequence,
59
69
  # then the shorter one is converted to EXCLUSIVE and marked as transmuted
60
- def trasmute_parts!
61
- insides = @parts.select { |p| p.is?(Part::SEAM) }
62
- return if insides.size < 2
63
-
64
- insides.each do |inside|
65
- (insides - [inside]).each do |inside_compare|
66
- next unless inside_compare.is?(Part::SEAM)
67
-
68
- count = 0
69
- inside.each do |position|
70
- inclusion = position.end_point.queues.include?(inside_compare)
71
- count += 1 if inclusion
70
+ def transmute_parts!
71
+ transpose = tile.cluster.finder.transpose?
72
+ if (current_seam = @first_seam)
73
+ loop do
74
+ if transpose
75
+ transmute_transposed_part(current_seam)
76
+ elsif !current_seam.transmutation_skip
77
+ current_seam.try_transmutation!
72
78
  end
73
- if count == inside.size && count < inside_compare.size
74
- inside.type = Part::EXCLUSIVE
75
- inside.trasmuted = true
76
- break
77
- end
78
- if count == inside.size && count == inside_compare.size &&
79
- inside.next.nil? && inside_compare.prev.nil?
80
- inside.mirror = true
79
+ current_seam = current_seam.next_seam
80
+ break if current_seam.nil?
81
+ end
82
+ end
83
+ end
84
+
85
+ def transmute_transposed_part(part)
86
+ if (current_seam = @first_seam)
87
+ loop do
88
+ if current_seam != part
89
+ if part.within?(current_seam)
90
+ if !part.same_length?(current_seam)
91
+ part.type = Part::EXCLUSIVE
92
+ part.trasmuted = true
93
+ part.head.end_point.queues.delete(part)
94
+ part.tail.end_point.queues.delete(part)
95
+ return
96
+ end
97
+ end
81
98
  end
99
+ current_seam = current_seam.next_seam
100
+ break if current_seam.nil?
82
101
  end
83
102
  end
84
103
  end
@@ -16,6 +16,10 @@ module Contrek
16
16
  transpose(super())
17
17
  end
18
18
 
19
+ def transpose?
20
+ true
21
+ end
22
+
19
23
  private
20
24
 
21
25
  def adjust(result)
@@ -51,7 +51,8 @@ module Contrek
51
51
  benchmarks: format_benchmarks,
52
52
  width: @source_bitmap.w,
53
53
  height: @source_bitmap.h,
54
- treemap: (@node_cluster.treemap if @options.has_key?(:treemap))
54
+ treemap: (@node_cluster.treemap if @options.has_key?(:treemap)),
55
+ versus: @options[:versus]
55
56
  }
56
57
  Result.new(@node_cluster.polygons, metadata)
57
58
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Contrek
4
- VERSION = "1.2.9"
4
+ VERSION = "1.3.1"
5
5
  end