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
@@ -0,0 +1,117 @@
1
+ /*
2
+ * StreamingMerger.cpp
3
+ *
4
+ * Copyright (c) 2025-2026 Emanuele Cesaroni
5
+ *
6
+ * Licensed under the GNU Affero General Public License v3 (AGPLv3).
7
+ * See the LICENSE file in this directory for the full license text.
8
+ */
9
+
10
+ #include "StreamingMerger.h"
11
+ #include <sstream>
12
+ #include <algorithm>
13
+ #include <vector>
14
+ #include <string>
15
+
16
+ StreamingMerger::StreamingMerger(int number_of_threads,
17
+ std::vector<std::string>* options,
18
+ std::ofstream* stream_to,
19
+ int total_width, int total_height)
20
+ : VerticalMerger(number_of_threads, options), stream(stream_to), total_width(total_width), total_height(total_height) {
21
+ if (!stream) {
22
+ throw std::invalid_argument("Streaming requires a valid destination output. stream_to cannot be null.");
23
+ }
24
+ if (total_width <= 0 || total_height <= 0) {
25
+ throw std::invalid_argument("Streaming requires valid canvas dimensions (width and height must be > 0).");
26
+ }
27
+ }
28
+
29
+ void StreamingMerger::add_tile(ProcessResult& result, bool flush)
30
+ { VerticalMerger::add_tile(result);
31
+ if (tiles_.size() == 2) {
32
+ this->process_tiles();
33
+ this->tiles_.queue_push(this->whole_tile);
34
+ this->stream_polygons(this->whole_tile, flush);
35
+ this->whole_tile->shapes().shrink_to_fit();
36
+ }
37
+ }
38
+
39
+ ProcessResult* StreamingMerger::process_info() {
40
+ ProcessResult *pr = VerticalMerger::process_info();
41
+ pr->groups = this->moved;
42
+ return(pr);
43
+ }
44
+
45
+ void StreamingMerger::stream_polygons(Tile* tile, bool flush) {
46
+ ensure_header();
47
+ if (int tile_end_x = tile->end_x(); true) {
48
+ tile->shapes().erase(
49
+ std::remove_if(tile->shapes().begin(), tile->shapes().end(), [this, flush, tile_end_x](Shape* shape) {
50
+ if (flush || shape->outer_polyline->max_x() < (tile_end_x - 1)) {
51
+ this->moved++;
52
+ this->stream_raw_polygon(shape);
53
+ shape->detach_from_pool();
54
+ return true;
55
+ }
56
+ return false;
57
+ }),
58
+ tile->shapes().end());
59
+ }
60
+ stream->flush();
61
+ if (flush) {
62
+ ensure_footer();
63
+ }
64
+ }
65
+
66
+ void StreamingMerger::stream_raw_polygon(const Shape* shape) {
67
+ std::ostringstream outer_oss;
68
+ const std::vector<Point>& points = shape->outer_polyline->raw();
69
+ for (size_t i = 0; i < points.size(); ++i) {
70
+ outer_oss << points[i].y << "," << points[i].x;
71
+ if (i < points.size() - 1) outer_oss << " ";
72
+ }
73
+ *stream << svg_outer_polygon_string(outer_oss.str());
74
+
75
+ for (const auto& inner_polyline : shape->inner_polylines) {
76
+ std::ostringstream inner_oss;
77
+ const std::vector<Point>& inner_points = inner_polyline->raw();
78
+ for (size_t i = 0; i < inner_points.size(); ++i) {
79
+ inner_oss << inner_points[i].y << "," << inner_points[i].x;
80
+ if (i < inner_points.size() - 1) inner_oss << " ";
81
+ }
82
+ *stream << svg_inner_polygon_string(inner_oss.str());
83
+ }
84
+ }
85
+
86
+ void StreamingMerger::ensure_header() {
87
+ if (stream && stream->tellp() == 0) {
88
+ *stream << svg_header_string();
89
+ }
90
+ }
91
+
92
+ void StreamingMerger::ensure_footer() {
93
+ if (stream) {
94
+ *stream << svg_footer_string();
95
+ }
96
+ }
97
+
98
+ std::string StreamingMerger::svg_css() {
99
+ return ".out{fill:none;stroke:red;stroke-width:1;}.in{fill:none;stroke:green;stroke-width:1;}.out:hover{stroke:yellow;}";
100
+ }
101
+
102
+ std::string StreamingMerger::svg_header_string() {
103
+ return "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"" + std::to_string(total_width) +
104
+ "\" height=\"" + std::to_string(total_height) + "\"><style>" + svg_css() + "</style>";
105
+ }
106
+
107
+ std::string StreamingMerger::svg_footer_string() {
108
+ return "</svg>";
109
+ }
110
+
111
+ std::string StreamingMerger::svg_outer_polygon_string(std::string_view points) {
112
+ return "<polygon points=\"" + std::string(points) + "\" class=\"out\"/>";
113
+ }
114
+
115
+ std::string StreamingMerger::svg_inner_polygon_string(std::string_view points) {
116
+ return "<polygon points=\"" + std::string(points) + "\" class=\"in\"/>";
117
+ }
@@ -0,0 +1,41 @@
1
+ /*
2
+ * StreamingMerger.h
3
+ *
4
+ * Copyright (c) 2025-2026 Emanuele Cesaroni
5
+ *
6
+ * Licensed under the GNU Affero General Public License v3 (AGPLv3).
7
+ * See the LICENSE file in this directory for the full license text.
8
+ */
9
+
10
+ #pragma once
11
+ #include "VerticalMerger.h"
12
+ #include <fstream>
13
+ #include <string>
14
+ #include <string_view>
15
+ #include <stdexcept>
16
+ #include <vector>
17
+
18
+ class StreamingMerger : public VerticalMerger {
19
+ private:
20
+ std::ofstream* stream;
21
+ int total_width;
22
+ int total_height;
23
+ int moved = 0;
24
+ void ensure_header();
25
+ void ensure_footer();
26
+ void stream_polygons(Tile* tile, bool flush = false);
27
+ void stream_raw_polygon(const Shape* shape);
28
+ virtual std::string svg_css();
29
+ virtual std::string svg_header_string();
30
+ virtual std::string svg_footer_string();
31
+ virtual std::string svg_outer_polygon_string(std::string_view points);
32
+ virtual std::string svg_inner_polygon_string(std::string_view points);
33
+
34
+ public:
35
+ StreamingMerger(int number_of_threads,
36
+ std::vector<std::string>* options,
37
+ std::ofstream* stream_to,
38
+ int total_width, int total_height);
39
+ void add_tile(ProcessResult& result, bool flush = false);
40
+ ProcessResult* process_info() override;
41
+ };
@@ -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"
@@ -96,6 +94,8 @@
96
94
  #include "PolygonFinder/src/polygon/finder/concurrent/HorizontalMerger.cpp"
97
95
  #include "PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.h"
98
96
  #include "PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.cpp"
97
+ #include "PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.h"
98
+ #include "PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.cpp"
99
99
  #include "PolygonFinder/src/polygon/finder/concurrent/ShapePool.h"
100
100
  #include "PolygonFinder/src/polygon/finder/concurrent/ShapePool.cpp"
101
101
  extern "C" {
@@ -184,24 +184,25 @@ class To_Ruby<ProcessResult*>
184
184
  return_me[Symbol("named_sequence")] = pr->named_sequence;
185
185
  return_me[Symbol("width")] = pr->width;
186
186
  return_me[Symbol("height")] = pr->height;
187
+ return_me[Symbol("versus")] = Symbol(pr->versus == Node::O ? "o" : "a");
187
188
 
188
189
  Rice::Array out;
189
190
  for (Polygon& x : pr->polygons)
190
191
  { Rice::Hash poly_hash = Rice::Hash();
191
- // OUTER: std::vector<Point*>
192
+ // OUTER: std::vector<Point>
192
193
  Rice::Array outer_flat;
193
- for (Point* p : x.outer) {
194
- outer_flat.push(p->x);
195
- outer_flat.push(p->y);
194
+ for (const Point& p : x.outer) {
195
+ outer_flat.push(p.x);
196
+ outer_flat.push(p.y);
196
197
  }
197
198
  poly_hash[Symbol("outer")] = outer_flat;
198
- // INNER: std::list<std::vector<Point*>>
199
+ // INNER: std::list<std::vector<Point>>
199
200
  Rice::Array inner_collection;
200
- for (const std::vector<Point*>& sequence : x.inner) {
201
+ for (const std::vector<Point>& sequence : x.inner) {
201
202
  Rice::Array sequence_flat;
202
- for (Point* p : sequence) {
203
- sequence_flat.push(p->x);
204
- sequence_flat.push(p->y);
203
+ for (const Point& p : sequence) {
204
+ sequence_flat.push(p.x);
205
+ sequence_flat.push(p.y);
205
206
  }
206
207
  inner_collection.push(sequence_flat);
207
208
  }
@@ -249,6 +250,7 @@ ProcessResult ruby_result_to_process_result(Rice::Object rb_result) {
249
250
  Rice::Hash metadata = rb_result.iv_get("@metadata_storage");
250
251
  pr.width = detail::From_Ruby<int>().convert(metadata[Symbol("width")].value());
251
252
  pr.height = detail::From_Ruby<int>().convert(metadata[Symbol("height")].value());
253
+ pr.versus = metadata[Symbol("versus")] == Symbol("o") ? Node::O : Node::A;
252
254
 
253
255
  Rice::Array rb_polygons = rb_result.iv_get("@polygons_storage");
254
256
  for (size_t i = 0; i < rb_polygons.size(); ++i) {
@@ -268,17 +270,17 @@ ProcessResult ruby_result_to_process_result(Rice::Object rb_result) {
268
270
  for (size_t j = 0; j < outer_flat.size(); j += 2) {
269
271
  int px = detail::From_Ruby<int>().convert(outer_flat[j].value());
270
272
  int py = detail::From_Ruby<int>().convert(outer_flat[j+1].value());
271
- poly.outer.push_back(new Point(px, py));
273
+ poly.outer.push_back(Point(px, py));
272
274
  }
273
275
  // INNER
274
276
  Rice::Array inner_collection = (Rice::Array)rb_poly[Symbol("inner")];
275
277
  for (size_t j = 0; j < inner_collection.size(); ++j) {
276
278
  Rice::Array sequence_flat = (Rice::Array)inner_collection[j];
277
- std::vector<Point*> hole;
279
+ std::vector<Point> hole;
278
280
  for (size_t k = 0; k < sequence_flat.size(); k += 2) {
279
281
  int px = detail::From_Ruby<int>().convert(sequence_flat[k].value());
280
282
  int py = detail::From_Ruby<int>().convert(sequence_flat[k+1].value());
281
- hole.push_back(new Point(px, py));
283
+ hole.push_back(Point(px, py));
282
284
  }
283
285
  poly.inner.push_back(hole);
284
286
  }
@@ -290,6 +292,36 @@ ProcessResult ruby_result_to_process_result(Rice::Object rb_result) {
290
292
 
291
293
  } // namespace Rice::detail
292
294
 
295
+ struct OfstreamWrapper {
296
+ std::string path;
297
+ std::ofstream stream;
298
+ OfstreamWrapper(std::string p) : path(p), stream(p, std::ios::out) {}
299
+ void close() { stream.close(); }
300
+ bool closed() { return !stream.is_open(); }
301
+ void rewind() { /* noop */ }
302
+ std::string read() {
303
+ stream.flush();
304
+ std::ifstream in(path);
305
+ return std::string((std::istreambuf_iterator<char>(in)),
306
+ std::istreambuf_iterator<char>());
307
+ }
308
+ std::ofstream& get_stream() { return stream; }
309
+ };
310
+
311
+ StreamingMerger* create_streaming_merger(Object self,
312
+ int number_of_threads,
313
+ std::vector<std::string>* options,
314
+ Object stream_obj,
315
+ int total_width,
316
+ int total_height) {
317
+ OfstreamWrapper* wrapper = Rice::detail::From_Ruby<OfstreamWrapper*>().convert(stream_obj.value());
318
+ return new StreamingMerger(number_of_threads, options, &wrapper->get_stream(), total_width, total_height);
319
+ }
320
+
321
+ OfstreamWrapper* create_ofstream(Object self, std::string path) {
322
+ return new OfstreamWrapper(path);
323
+ }
324
+
293
325
  extern "C"
294
326
  void Init_cpp_polygon_finder() {
295
327
  #ifdef HAVE_TCMALLOC
@@ -384,9 +416,27 @@ void Init_cpp_polygon_finder() {
384
416
  define_class<HorizontalMerger, Merger>("CPPHorizontalMerger")
385
417
  .define_constructor(Constructor<HorizontalMerger, int, std::vector<std::string>*>(), Arg("number_of_threads"), Arg("options") = nullptr, Arg("yield_gvl") = true);
386
418
 
387
- Data_Type<VerticalMerger> rb_cVerticalMerger =
419
+ Data_Type<VerticalMerger> rb_cVerticalMerger =
388
420
  define_class<VerticalMerger, Merger>("CPPVerticalMerger")
389
- .define_constructor(Constructor<VerticalMerger, int, std::vector<std::string>*>(), Arg("number_of_threads"), Arg("options") = nullptr, Arg("yield_gvl") = true);
421
+ .define_constructor(Constructor<VerticalMerger, int, std::vector<std::string>*>(), Arg("number_of_threads"), Arg("options") = nullptr, Arg("yield_gvl") = true)
422
+ .define_method("add_tile", [](VerticalMerger& self, Object rb_result) {
423
+ ProcessResult pr = Rice::detail::ruby_result_to_process_result(rb_result);
424
+ self.add_tile(pr);
425
+ });
426
+
427
+ Data_Type<OfstreamWrapper> rb_cstd_ofstream = define_class<OfstreamWrapper>("CPPOfstream");
428
+ rb_cstd_ofstream.define_singleton_method("new", &create_ofstream);
429
+ rb_cstd_ofstream.define_method("close", [](OfstreamWrapper& self) { self.close(); });
430
+ rb_cstd_ofstream.define_method("closed?", [](OfstreamWrapper& self) { return self.closed(); });
431
+ rb_cstd_ofstream.define_method("rewind", [](OfstreamWrapper& self) { self.rewind(); });
432
+ rb_cstd_ofstream.define_method("read", [](OfstreamWrapper& self) { return self.read(); });
433
+
434
+ Data_Type<StreamingMerger> rb_cstreaming_merger = define_class<StreamingMerger, VerticalMerger>("CPPStreamingMerger");
435
+ rb_cstreaming_merger.define_method("add_tile", [](StreamingMerger& self, Object rb_result, bool flush) {
436
+ ProcessResult pr = Rice::detail::ruby_result_to_process_result(rb_result);
437
+ self.add_tile(pr, flush);
438
+ });
439
+ rb_cstreaming_merger.define_singleton_method("new", &create_streaming_merger);
390
440
 
391
441
  Module mContrek = define_module("Contrek");
392
442
  Module mCpp = define_module_under(mContrek, "Cpp");
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "mkmf-rice"
2
4
 
3
5
  has_tcmalloc = find_library("tcmalloc", "malloc")
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Contrek
2
4
  module Bitmaps
3
5
  class Bitmap
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Contrek
2
4
  module Bitmaps
3
5
  class ChunkyBitmap < Bitmap
@@ -87,6 +89,17 @@ module Contrek
87
89
  puts
88
90
  end
89
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
+
90
103
  private
91
104
 
92
105
  def next_color(color)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Contrek
2
4
  module Bitmaps
3
5
  module Painting
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "chunky_png"
2
4
 
3
5
  module Contrek
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Contrek
2
4
  module Bitmaps
3
5
  class RawBitmap < PngBitmap
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Contrek
2
4
  module Bitmaps
3
5
  class RgbColor
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Contrek
2
4
  module Bitmaps
3
5
  class RgbCppColor
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Contrek
2
4
  module Bitmaps
3
5
  class SampleGenerator
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Contrek
2
4
  module Cpp
3
5
  class CPPConcurrentFinder < CPPFinder
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Contrek
2
4
  module Cpp
3
5
  class CPPConcurrentHorizontalMerger < CPPHorizontalMerger