contrek 1.0.4 → 1.0.6

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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -3
  3. data/CHANGELOG.md +21 -0
  4. data/Gemfile.lock +4 -4
  5. data/README.md +34 -30
  6. data/Rakefile +3 -0
  7. data/contrek.gemspec +7 -4
  8. data/ext/cpp_polygon_finder/PolygonFinder/Makefile +44 -0
  9. data/ext/cpp_polygon_finder/PolygonFinder/images/sample_10240x10240.png +0 -0
  10. data/ext/cpp_polygon_finder/PolygonFinder/src/Main.cpp +14 -5
  11. data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +136 -15
  12. data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.h +5 -4
  13. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/CpuTimer.h +44 -0
  14. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/Bitmap.cpp +8 -0
  15. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/Bitmap.h +3 -4
  16. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/FastPngBitmap.cpp +63 -573
  17. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/FastPngBitmap.h +17 -18
  18. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/RemoteFastPngBitmap.cpp +22 -5
  19. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/RemoteFastPngBitmap.h +4 -8
  20. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/spng.c +6980 -0
  21. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/spng.h +537 -0
  22. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/FinderUtils.cpp +101 -0
  23. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/FinderUtils.h +16 -0
  24. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/List.cpp +0 -3
  25. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/List.h +4 -7
  26. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Lists.cpp +13 -13
  27. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Lists.h +5 -7
  28. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.cpp +47 -41
  29. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.h +15 -10
  30. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.cpp +181 -178
  31. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.h +19 -20
  32. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Polygon.h +20 -0
  33. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.cpp +52 -137
  34. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +85 -16
  35. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/RectBounds.h +39 -0
  36. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ClippedPolygonFinder.cpp +14 -0
  37. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ClippedPolygonFinder.h +17 -0
  38. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.cpp +117 -0
  39. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.h +32 -0
  40. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.cpp +344 -0
  41. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.h +46 -0
  42. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/EndPoint.cpp +14 -0
  43. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/EndPoint.h +22 -0
  44. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/FakeCluster.cpp +13 -0
  45. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/FakeCluster.h +17 -0
  46. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.cpp +138 -0
  47. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.h +52 -0
  48. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Hub.cpp +23 -0
  49. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Hub.h +40 -0
  50. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.cpp +70 -0
  51. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.h +47 -0
  52. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/PartPool.cpp +24 -0
  53. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/PartPool.h +23 -0
  54. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.cpp +182 -0
  55. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.h +30 -0
  56. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +108 -0
  57. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +52 -0
  58. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Poolable.cpp +59 -0
  59. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Poolable.h +52 -0
  60. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.cpp +31 -0
  61. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.h +25 -0
  62. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Queue.h +36 -0
  63. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Queueable.h +230 -0
  64. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.cpp +35 -0
  65. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.h +20 -0
  66. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.cpp +26 -0
  67. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.h +23 -0
  68. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.cpp +105 -0
  69. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.h +56 -0
  70. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/Matcher.cpp +3 -3
  71. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/Matcher.h +5 -8
  72. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/RGBMatcher.h +3 -7
  73. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/RGBNotMatcher.cpp +2 -2
  74. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/RGBNotMatcher.h +4 -8
  75. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/ValueNotMatcher.cpp +2 -2
  76. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/ValueNotMatcher.h +3 -7
  77. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/LinearReducer.cpp +23 -15
  78. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/LinearReducer.h +6 -8
  79. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/Reducer.cpp +2 -5
  80. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/Reducer.h +4 -8
  81. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/UniqReducer.cpp +9 -12
  82. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/UniqReducer.h +3 -7
  83. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/VisvalingamReducer.cpp +26 -27
  84. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/VisvalingamReducer.h +76 -87
  85. data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +64 -32
  86. data/ext/cpp_polygon_finder/extconf.rb +14 -0
  87. data/lib/contrek/bitmaps/sample_generator.rb +56 -0
  88. data/lib/contrek/cpp/cpp_concurrent_finder.rb +9 -0
  89. data/lib/contrek/finder/bounds.rb +17 -0
  90. data/lib/contrek/finder/concurrent/cluster.rb +2 -2
  91. data/lib/contrek/finder/concurrent/cursor.rb +8 -8
  92. data/lib/contrek/finder/concurrent/finder.rb +10 -9
  93. data/lib/contrek/finder/concurrent/part.rb +2 -2
  94. data/lib/contrek/finder/concurrent/partitionable.rb +1 -1
  95. data/lib/contrek/finder/concurrent/polyline.rb +17 -15
  96. data/lib/contrek/finder/concurrent/sequence.rb +11 -0
  97. data/lib/contrek/finder/concurrent/tile.rb +3 -3
  98. data/lib/contrek/finder/node_cluster.rb +16 -8
  99. data/lib/contrek/finder/polygon_finder.rb +1 -4
  100. data/lib/contrek/version.rb +1 -1
  101. data/lib/contrek.rb +9 -1
  102. metadata +62 -15
  103. data/ext/cpp_polygon_finder/PolygonFinder/.cproject +0 -136
  104. data/ext/cpp_polygon_finder/PolygonFinder/.project +0 -27
  105. data/ext/cpp_polygon_finder/PolygonFinder/.settings/org.eclipse.ltk.core.refactoring.prefs +0 -2
  106. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/PngBitmap.cpp +0 -48
  107. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/PngBitmap.h +0 -32
@@ -6,116 +6,104 @@
6
6
  * Copyright 2025 Emanuele Cesaroni
7
7
  */
8
8
 
9
- #include "NodeCluster.h"
10
- #include "Node.h"
11
- #include "../reducers/UniqReducer.h"
12
- #include "../reducers/LinearReducer.h"
13
- #include "../reducers/VisvalingamReducer.h"
14
9
  #include <iostream>
15
10
  #include <list>
16
11
  #include <algorithm>
17
12
  #include <map>
18
13
  #include <string>
19
14
  #include <vector>
15
+ #include <utility>
16
+ #include "NodeCluster.h"
17
+ #include "Node.h"
18
+ #include "RectBounds.h"
19
+ #include "../reducers/UniqReducer.h"
20
+ #include "../reducers/LinearReducer.h"
21
+ #include "../reducers/VisvalingamReducer.h"
20
22
 
21
- NodeCluster::NodeCluster(int h, pf_Options *options) {
22
- this->vert_nodes = new std::vector<Node*>[h];
23
+ NodeCluster::NodeCluster(int h, int w, pf_Options *options) {
23
24
  versus_inverter[Node::O] = Node::A;
24
25
  versus_inverter[Node::A] = Node::O;
25
26
  this->options = options;
26
27
  this->height = h;
28
+ this->width = w;
27
29
  this->nodes = 0;
28
- this->plot_sequence = nullptr;
29
- this->sequence_coords = nullptr;
30
- this->sequences = new std::list<std::list<Node*>*>();
30
+
31
+ this->vert_nodes.resize(h);
32
+ for (int i = 0; i < h; ++i) {
33
+ this->vert_nodes[i].reserve(w/2);
34
+ }
31
35
 
32
36
  this->root_nodes = this->lists.add_list();
33
37
  this->inner_plot = this->lists.add_list();
34
38
  this->inner_new = this->lists.add_list();
39
+
40
+ this->points.reserve(w * h);
35
41
  }
36
42
 
37
43
  NodeCluster::~NodeCluster() {
38
44
  }
39
45
 
40
- void NodeCluster::compress_coords(pf_Options options) {
41
- if (options.compress_linear || options.compress_uniq || options.compress_visvalingam)
42
- { std::list<std::list<Point*>*> sequences;
43
- for (std::list<std::map<std::string, std::list<std::list<Point*>*>>>::iterator x = this->polygons.begin(); x != this->polygons.end(); ++x)
44
- { for (std::list<std::list<Point*>*>::iterator y = (*x)["outer"].begin(); y != (*x)["outer"].end(); ++y)
45
- { sequences.push_back(*y);
46
- }
47
- for (std::list<std::list<Point*>*>::iterator y = (*x)["inner"].begin(); y != (*x)["inner"].end(); ++y)
48
- { sequences.push_back(*y);
49
- }
46
+ void NodeCluster::compress_coords(std::list<Polygon>& polygons, pf_Options options) {
47
+ if (!(options.compress_linear || options.compress_uniq || options.compress_visvalingam)) return;
48
+
49
+ auto compress_sequence = [&](std::vector<Point*>& points_vec) {
50
+ if (points_vec.empty()) return;
51
+
52
+ if (options.compress_uniq) {
53
+ UniqReducer uniq_reducer(points_vec);
54
+ uniq_reducer.reduce();
50
55
  }
51
- if (options.compress_uniq)
52
- { for (std::list<std::list<Point*>*>::iterator it = sequences.begin(); it != sequences.end(); ++it)
53
- { UniqReducer reducer(*it);
54
- reducer.reduce();
55
- }
56
+ if (options.compress_linear) {
57
+ LinearReducer linear_reducer(points_vec);
58
+ linear_reducer.reduce();
56
59
  }
57
- if (options.compress_linear)
58
- { for (std::list<std::list<Point*>*>::iterator it = sequences.begin(); it != sequences.end(); ++it)
59
- { LinearReducer reducer(*it);
60
- reducer.reduce();
61
- }
60
+ if (options.compress_visvalingam) {
61
+ VisvalingamReducer vis_reducer(points_vec, options.compress_visvalingam_tolerance);
62
+ vis_reducer.reduce();
62
63
  }
63
- if (options.compress_visvalingam)
64
- { for (std::list<std::list<Point*>*>::iterator it = sequences.begin(); it != sequences.end(); ++it)
65
- { VisvalingamReducer reducer(*it, options.compress_visvalingam_tolerance);
66
- reducer.reduce();
67
- }
64
+ };
65
+ for (auto &poly : polygons) {
66
+ compress_sequence(poly.outer);
67
+ for (auto &inner_seq : poly.inner) {
68
+ compress_sequence(inner_seq);
68
69
  }
69
70
  }
70
71
  }
71
72
 
72
-
73
73
  void NodeCluster::build_tangs_sequence() {
74
- for (int line = 0; line < this->height; line++)
75
- { for (std::vector<Node*>::iterator node = vert_nodes[line].begin(); node != vert_nodes[line].end(); ++node)
76
- { (*node)->precalc_tangs_sequences();
74
+ for (auto& line : vert_nodes) {
75
+ for (Node& node : line) {
76
+ node.precalc_tangs_sequences(this->points);
77
77
  }
78
78
  }
79
79
  }
80
80
 
81
- void NodeCluster::add_node(Node *node) {
81
+ Node* NodeCluster::add_node(int min_x, int max_x, int y, char name) {
82
+ vert_nodes[y].emplace_back(min_x, max_x, y, name);
83
+
84
+ Node& node = vert_nodes[y].back();
85
+ node.data_pointer = this->lists.get_data_pointer();
86
+ node.abs_x_index = vert_nodes[y].size() - 1;
82
87
  this->nodes++;
83
- node->data_pointer = this->lists.get_data_pointer();
84
- node->abs_x_index = vert_nodes[node->y].size();
85
- vert_nodes[node->y].push_back(node);
86
- root_nodes->push_back(node);
87
-
88
- if (node->y > 0)
89
- { std::vector<Node*> *up_nodes = &vert_nodes[node->y - 1];
90
- int up_nodes_count = up_nodes->size();
91
- Node *up_node;
92
- if (up_nodes_count > 0)
93
- { int index = 0;
94
- do
95
- { up_node = (*up_nodes)[index];
96
- if (up_node->max_x >= node->min_x)
97
- { if (up_node->min_x <= node->max_x)
98
- { node->add_intersection(up_node);
99
- (up_node)->add_intersection(node);
100
- }
101
- if (++index == up_nodes_count) return;
102
- do
103
- { up_node = (*up_nodes)[index];
104
- if (up_node->min_x <= node->max_x)
105
- { node->add_intersection(up_node);
106
- (up_node)->add_intersection(node);
107
- }
108
- else return;
109
- }while (++index != up_nodes_count);
110
- return;
111
- }
112
- }while(++index != up_nodes_count);
88
+
89
+ root_nodes->push_back(&node);
90
+
91
+ if (y > 0) {
92
+ std::vector<Node>& up_nodes = vert_nodes[y - 1];
93
+ if (!up_nodes.empty()) {
94
+ auto it = std::lower_bound(up_nodes.begin(), up_nodes.end(), node.min_x,
95
+ [](const Node& a, int val) {
96
+ return a.max_x < val;
97
+ });
98
+ while (it != up_nodes.end()) {
99
+ if (it->min_x > node.max_x) break;
100
+ node.add_intersection(&(*it));
101
+ it->add_intersection(&node);
102
+ ++it;
103
+ }
113
104
  }
114
105
  }
115
- }
116
-
117
- std::list<Point*>* NodeCluster::get_coords() {
118
- return(this->sequence_coords);
106
+ return &node;
119
107
  }
120
108
 
121
109
  void NodeCluster::plot(int versus) {
@@ -124,48 +112,47 @@ void NodeCluster::plot(int versus) {
124
112
  Node *next_node;
125
113
 
126
114
  while (root_nodes->size() > 0)
127
- { Node *root_node = (Node*) root_nodes->shift();
115
+ { Node *root_node = reinterpret_cast<Node*>(root_nodes->shift());
128
116
  root_node->outer_index = index_order;
129
- this->plot_sequence = new std::list<Node*>();
130
- this->sequence_coords = new std::list<Point*>();
131
-
132
- plot_sequence->push_back(root_node);
117
+ this->plot_sequence.clear();
118
+ this->plot_sequence.push_back(root_node);
119
+ Polygon poly;
133
120
 
134
- if ((root_node)->tangs_sequence->size() > 0) // front() on empty list is undefined
135
- { versus == Node::A ? next_node = root_node->tangs_sequence->back()->node : next_node = root_node->tangs_sequence->front()->node;
121
+ if ((root_node)->tangs_sequence.size() > 0) // front() on empty list is undefined
122
+ { versus == Node::A ? next_node = root_node->tangs_sequence.back().node : next_node = root_node->tangs_sequence.front().node;
136
123
  if (next_node != nullptr)
137
- { sequence_coords->push_back(next_node->coords_entering_to(root_node, versus_inverter[versus], Node::OUTER));
124
+ { Point* p = next_node->coords_entering_to(root_node, versus_inverter[versus], Node::OUTER);
125
+ poly.outer.push_back(p);
126
+ poly.bounds.expand(p->x, p->y);
138
127
  }
139
128
  if ((this->nodes > 0) && (next_node != nullptr))
140
- { plot_node(next_node, root_node, versus);
129
+ { plot_node(poly.outer, next_node, root_node, versus, poly.bounds);
130
+ }
131
+ this->sequences.push_back(std::move(this->plot_sequence));
132
+ this->plot_sequence.clear();
133
+
134
+ if (poly.outer.size() > 2)
135
+ { this->polygons.push_back(poly);
141
136
  }
142
- this->sequences->push_back(plot_sequence);
143
- std::list<std::list<Point*>*> outer_container, inner_container;
144
- outer_container.push_back(sequence_coords);
145
- std::list<Point*> pl_inner;
146
- std::map<std::string, std::list<std::list<Point*>*>> poly;
147
- poly["outer"] = outer_container;
148
- poly["inner"] = inner_container;
149
- if (sequence_coords->size() > 2) this->polygons.push_back(poly);
150
137
 
151
138
  int index_inner = 0;
152
139
  while (inner_plot->size() > 0)
153
- { this->plot_sequence = new std::list<Node*>();
154
- this->sequence_coords = new std::list<Point*>();
140
+ { this->plot_sequence.clear();
141
+ std::vector<Point*> inner_sequence;
155
142
  std::list<Node*>::iterator first_i;
156
143
  Node *first = nullptr;
157
144
 
158
145
  Listable *act = inner_plot->first();
159
146
  do
160
- { if (((Node*)act)->tangs_count <= 2)
161
- { first = (Node*) act;
147
+ { if ((reinterpret_cast<Node*>(act))->tangs_count <= 2)
148
+ { first = reinterpret_cast<Node*>(act);
162
149
  break;
163
150
  }
164
151
  }while((act = act->data_pointer[inner_plot->get_id()].next) != nullptr);
165
152
 
166
- if (first == nullptr) first = (Node*) inner_plot->first();
153
+ if (first == nullptr) first = reinterpret_cast<Node*>(inner_plot->first());
167
154
 
168
- plot_sequence->push_back(first);
155
+ plot_sequence.push_back(first);
169
156
  inner_plot->remove(first);
170
157
  root_nodes->remove(first);
171
158
 
@@ -181,16 +168,16 @@ void NodeCluster::plot(int versus) {
181
168
  }
182
169
 
183
170
  if (next_node != nullptr)
184
- { sequence_coords->push_back(next_node->coords_entering_to(first, inner_v, Node::INNER));
185
- plot_inner_node(next_node, inner_v, first, root_node);
171
+ { inner_sequence.push_back(next_node->coords_entering_to(first, inner_v, Node::INNER));
172
+ plot_inner_node(inner_sequence, next_node, inner_v, first, root_node);
186
173
  }
187
-
188
- this->polygons.back()["inner"].push_back(sequence_coords);
174
+ this->polygons.back().inner.push_back(inner_sequence);
189
175
  this->inner_plot->grab(this->inner_new);
190
176
  index_inner++;
191
177
  }
192
178
  } else {
193
- this->sequences->push_back(plot_sequence);
179
+ this->sequences.push_back(std::move(this->plot_sequence));
180
+ this->plot_sequence.clear();
194
181
  }
195
182
  // tree
196
183
  if (this->options->treemap)
@@ -200,110 +187,126 @@ void NodeCluster::plot(int versus) {
200
187
  }
201
188
  }
202
189
 
203
- int *NodeCluster::test_in_hole_a(Node *node)
190
+ std::pair<int, int> NodeCluster::test_in_hole_a(Node* node)
204
191
  { if (node->outer_index > 0)
205
192
  { int start_left = node->abs_x_index - 1;
206
- do
207
- { Node *prev = this->vert_nodes[node->y][start_left];
193
+ do {
194
+ Node* prev = &this->vert_nodes[node->y][start_left];
208
195
  int cindex = prev->outer_index;
209
- if ((cindex < node->outer_index) && ((prev->track & Node::IMAX) != 0))
196
+
197
+ if ((cindex < node->outer_index) && (prev->track & Node::IMAX))
210
198
  { unsigned int start_right = node->abs_x_index;
211
199
  unsigned int line_size = this->vert_nodes[node->y].size();
212
200
  while (++start_right != line_size)
213
- { Node *tnext = this->vert_nodes[node->y][start_right];
214
- if (tnext->outer_index == cindex)
215
- { if ((tnext->track & Node::IMIN) != 0) return(new int[2] {cindex, prev->inner_index});
216
- else return(new int[2] {-1, -1});
201
+ { Node* tnext = &this->vert_nodes[node->y][start_right];
202
+ if (tnext->outer_index == cindex) {
203
+ if (tnext->track & Node::IMIN) return {cindex, prev->inner_index};
204
+ else return {-1, -1};
217
205
  }
218
206
  }
219
207
  }
220
- }while(--start_left >= 0);
208
+ } while (--start_left >= 0);
221
209
  }
222
- return(new int[2] {-1, -1});
210
+ return {-1, -1};
223
211
  }
224
212
 
225
- int *NodeCluster::test_in_hole_o(Node *node)
226
- { unsigned int line_size = this->vert_nodes[node->y].size();
227
- if ((node->outer_index) > 0 && (vert_nodes[node->y].back() != node))
228
- { unsigned int start_left = node->abs_x_index + 1;
229
- do
230
- { Node *prev = this->vert_nodes[node->y][start_left];
231
- int cindex = prev->outer_index;
232
- if ((cindex < node->outer_index) && ((prev->track & Node::IMIN) != 0))
233
- { int start_right = node->abs_x_index;
234
- while (--start_right >= 0)
235
- { Node *tnext = this->vert_nodes[node->y][start_right];
236
- if (tnext->outer_index == cindex)
237
- { if ((tnext->track & Node::IMAX) != 0) return(new int[2] {cindex, prev->inner_index});
238
- else return(new int[2] {-1, -1});
239
- }
213
+ std::pair<int, int> NodeCluster::test_in_hole_o(Node* node)
214
+ { auto& line = this->vert_nodes[node->y];
215
+ const unsigned int line_size = line.size();
216
+ if (node->outer_index == 0 || &line.back() == node) return {-1, -1};
217
+
218
+ unsigned int start_left = node->abs_x_index + 1;
219
+ do {
220
+ Node* prev = &line[start_left];
221
+ int cindex = prev->outer_index;
222
+
223
+ if (cindex < node->outer_index && (prev->track & Node::IMIN))
224
+ { int start_right = node->abs_x_index;
225
+ while (--start_right >= 0) {
226
+ Node* tnext = &line[start_right];
227
+ if (tnext->outer_index == cindex) {
228
+ if (tnext->track & Node::IMAX) return {cindex, prev->inner_index};
229
+ else return {-1, -1};
240
230
  }
241
231
  }
242
- }while(++start_left != line_size);
243
- }
244
- return(new int[2] {-1, -1});
232
+ }
233
+ } while (++start_left != line_size);
234
+ return {-1, -1};
245
235
  }
246
236
 
247
- void NodeCluster::plot_inner_node(Node *node, int versus, Node *stop_at, Node *start_node) {
248
- node->outer_index = start_node->outer_index;
249
- node->inner_index = stop_at->inner_index;
250
- root_nodes->remove(node);
251
- inner_plot->remove(node);
237
+ void NodeCluster::plot_inner_node(std::vector<Point*>& sequence_coords, Node *node, int versus, Node *stop_at, Node *start_node) {
238
+ Node *current_node = node;
252
239
 
253
- Node *last_node = plot_sequence->back();
254
- Node *next_node = node->my_next_inner(last_node, versus);
240
+ while (current_node != nullptr) {
241
+ current_node->outer_index = start_node->outer_index;
242
+ current_node->inner_index = stop_at->inner_index;
243
+ root_nodes->remove(current_node);
244
+ inner_plot->remove(current_node);
255
245
 
256
- plot_sequence->push_back(node);
246
+ Node *last_node = plot_sequence.back();
247
+ Node *next_node = current_node->my_next_inner(last_node, versus);
257
248
 
258
- bool plot = true;
259
- if (next_node -> y == last_node -> y)
260
- { Node *n = (versus == Node::A ? node->tangs_sequence->front()->node : node->tangs_sequence->back()->node);
261
- plot = (n == next_node);
262
- }
263
- if (plot)
264
- { sequence_coords->push_back(last_node->coords_entering_to(node, versus_inverter[versus], Node::INNER));
265
- if (node != start_node)
266
- { if (last_node->y == next_node->y)
267
- { sequence_coords->push_back(next_node->coords_entering_to(node, versus, Node::INNER));
249
+ plot_sequence.push_back(current_node);
250
+
251
+ bool plot = true;
252
+ if (next_node->y == last_node->y) {
253
+ Node *n = (versus == Node::A ? current_node->tangs_sequence.front().node : current_node->tangs_sequence.back().node);
254
+ plot = (n == next_node);
255
+ }
256
+ if (plot) {
257
+ sequence_coords.push_back(last_node->coords_entering_to(current_node, versus_inverter[versus], Node::INNER));
258
+ if (current_node != start_node) {
259
+ if (last_node->y == next_node->y) {
260
+ sequence_coords.push_back(next_node->coords_entering_to(current_node, versus, Node::INNER));
261
+ }
268
262
  }
269
263
  }
264
+ if (current_node->track_uncomplete()) {
265
+ this->inner_new->push_back(current_node);
266
+ } else {
267
+ inner_new->remove(current_node);
268
+ }
269
+ if (next_node == stop_at) break;
270
+ current_node = next_node;
270
271
  }
271
- if (node->track_uncomplete())
272
- { this->inner_new->push_back(node);
273
- } else {
274
- inner_new->remove(node);
275
- }
276
- if (next_node == stop_at) return;
277
- plot_inner_node(next_node, versus, stop_at, start_node);
278
272
  }
279
273
 
280
- void NodeCluster::plot_node(Node *node, Node *start_node, int versus) {
281
- root_nodes->remove(node);
282
- node->outer_index = start_node->outer_index;
283
- Node *last_node = plot_sequence->back();
284
- Node *next_node = node->my_next_outer(last_node, versus);
285
-
286
- plot_sequence->push_back(node);
287
- bool plot = true;
288
- if (next_node -> y == last_node -> y)
289
- { Node *n = (versus == Node::A ? node->tangs_sequence->back()->node : node->tangs_sequence->front()->node);
290
- plot = (n == next_node);
291
- }
274
+ void NodeCluster::plot_node(std::vector<Point*>& sequence_coords, Node *node, Node *start_node, int versus, RectBounds& bounds) {
275
+ Node *current_node = node;
276
+
277
+ while (current_node != nullptr) {
278
+ root_nodes->remove(current_node);
279
+ current_node->outer_index = start_node->outer_index;
292
280
 
293
- if (plot)
294
- { sequence_coords->push_back(last_node->coords_entering_to(node, versus, Node::OUTER));
295
- if (node != start_node)
296
- { inner_plot->contains(node) ? inner_plot->remove(node) : inner_plot->push_back(node);
297
- if (last_node->y == next_node->y)
298
- { sequence_coords->push_back(next_node->coords_entering_to(node, versus_inverter[versus], Node::OUTER));
299
- inner_plot->contains(node) ? inner_plot->remove(node) : inner_plot->push_back(node);
281
+ Node *last_node = plot_sequence.back();
282
+ Node *next_node = current_node->my_next_outer(last_node, versus);
283
+
284
+ plot_sequence.push_back(current_node);
285
+
286
+ bool plot = true;
287
+ if (next_node->y == last_node->y) {
288
+ Node *n = (versus == Node::A ? current_node->tangs_sequence.back().node : current_node->tangs_sequence.front().node);
289
+ plot = (n == next_node);
290
+ }
291
+ if (plot) {
292
+ Point* p = last_node->coords_entering_to(current_node, versus, Node::OUTER);
293
+ sequence_coords.push_back(p);
294
+ bounds.expand(p->x, p->y);
295
+ if (current_node != start_node) {
296
+ inner_plot->contains(current_node) ? inner_plot->remove(current_node) : inner_plot->push_back(current_node);
297
+ if (last_node->y == next_node->y) {
298
+ Point* p1 = next_node->coords_entering_to(current_node, versus_inverter[versus], Node::OUTER);
299
+ sequence_coords.push_back(p1);
300
+ bounds.expand(p1->x, p1->y);
301
+ inner_plot->contains(current_node) ? inner_plot->remove(current_node) : inner_plot->push_back(current_node);
302
+ }
300
303
  }
301
304
  }
305
+ if (current_node == start_node) {
306
+ if (current_node->track_complete()) break;
307
+ }
308
+ current_node = next_node;
302
309
  }
303
- if (node == start_node)
304
- { if (node->track_complete()) return;
305
- }
306
- plot_node(next_node, start_node, versus);
307
310
  }
308
311
 
309
312
  void NodeCluster::list_track(Node *node, std::list<Node*> *list) {
@@ -6,14 +6,16 @@
6
6
  * Copyright 2025 Emanuele Cesaroni
7
7
  */
8
8
 
9
- #ifndef POLYGON_FINDER_NODECLUSTER_H_
10
- #define POLYGON_FINDER_NODECLUSTER_H_
9
+ #pragma once
11
10
  #include <list>
12
11
  #include <vector>
13
12
  #include <map>
14
13
  #include <string>
14
+ #include <utility>
15
15
  #include "PolygonFinder.h"
16
16
  #include "Lists.h"
17
+ #include "RectBounds.h"
18
+ #include "Polygon.h"
17
19
 
18
20
  class Node;
19
21
  struct Point;
@@ -21,39 +23,36 @@ struct pf_Options;
21
23
 
22
24
  class NodeCluster {
23
25
  private:
24
- void plot_node(Node *node, Node *start_node, int versus);
25
- void plot_inner_node(Node *node, int versus, Node *stop_at, Node *start_node);
26
- std::list<Node*> *plot_sequence;
26
+ void plot_node(std::vector<Point*>& sequence_coords, Node *node, Node *start_node, int versus, RectBounds& bounds);
27
+ void plot_inner_node(std::vector<Point*>& sequence_coords, Node *node, int versus, Node *stop_at, Node *start_node);
28
+ std::vector<Node*> plot_sequence;
27
29
  List *inner_plot;
28
- std::list<Point*> *sequence_coords;
29
30
  List *inner_new;
30
31
  int versus_inverter[2];
31
32
  int count = 0;
32
33
  int nodes;
33
- pf_Options *options;
34
+ std::vector<Point> points;
34
35
 
35
36
  public:
36
- std::list<int*> treemap;
37
- int *test_in_hole_a(Node *node);
38
- int *test_in_hole_o(Node *node);
39
- std::vector<Node*> *vert_nodes;
37
+ pf_Options *options;
38
+ std::vector<std::pair<int, int>> treemap; // [a,b] a = index of parent outer, b = index of inner of parent outer
39
+ std::pair<int, int> test_in_hole_a(Node* node);
40
+ std::pair<int, int> test_in_hole_o(Node* node);
41
+ std::vector<std::vector<Node>> vert_nodes;
40
42
  void list_track(Node *node, std::list<Node*> *list);
41
43
  void list_delete(Node *node, std::list<Node*> *list);
42
44
  bool list_present(Node *node, std::list<Node*> *list);
43
- void compress_coords(pf_Options options);
45
+ void compress_coords(std::list<Polygon>& polygons, pf_Options options);
44
46
  List *root_nodes;
45
- int height;
46
- std::list<std::map<std::string, std::list<std::list<Point*>*>>> polygons;
47
- NodeCluster(int h, pf_Options *options);
47
+ int height, width;
48
+ std::list<Polygon> polygons;
49
+ NodeCluster(int h, int w, pf_Options *options);
48
50
  virtual ~NodeCluster();
49
- void add_node(Node *node);
51
+ Node* add_node(int min_x, int max_x, int y, char name);
50
52
  void calc_root_nodes();
51
53
  void build_tangs_sequence();
52
54
  void plot(int versus);
53
55
  Lists lists;
54
56
  std::list<Node*>::iterator exam(std::list<Node*>::iterator inode, Node *node, Node *father, Node *root_node);
55
- std::list<Point*>* get_coords();
56
- std::list<std::list<Node*>*> *sequences;
57
+ std::vector<std::vector<Node*>> sequences;
57
58
  };
58
-
59
- #endif /* POLYGON_FINDER_NODECLUSTER_H_ */
@@ -0,0 +1,20 @@
1
+ /*
2
+ * Polygon.h
3
+ *
4
+ * Created on: 23 nov 2025
5
+ * Author: ema
6
+ * Copyright 2025 Emanuele Cesaroni
7
+ */
8
+
9
+ #pragma once
10
+ #include <vector>
11
+ #include <list>
12
+ #include "Node.h"
13
+ #include "RectBounds.h"
14
+
15
+ struct Polygon {
16
+ std::vector<Point*> outer;
17
+ std::list<std::vector<Point*>> inner;
18
+ RectBounds bounds;
19
+ Polygon() : bounds(RectBounds::empty()) {}
20
+ };