contrek 1.1.8 → 1.1.9

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4fa95266798ecc7809dececd0fe6a0153ada90dbc5bbc9a22f418654ae6ab920
4
- data.tar.gz: 064e8757c2be8ea55c6e2b688d0b614ad5080bf741bbeef90fa3a204cf6815f8
3
+ metadata.gz: 87e8665985a5c9b3818f5f405609c8bf0f9d81dfaa197054e0801acdc60dc56c
4
+ data.tar.gz: 450c56eda5bd65ab936fcd52b37e3f8edbc2ec0ac852aa0cc4c052ee6d81ab7e
5
5
  SHA512:
6
- metadata.gz: 29b8d97fd331a3ee586729700c58070c0d3f849762c38265c59f6b7994d4a0fdc111f774b044835ae8dbc1de6905b0b2eabe92376549c08d16c9721aa5ee5ef1
7
- data.tar.gz: 553b23d74c214bb78e33e2243fd7bd0b600abd8f953acb21554cf2ca59498312f95fda3d6daafa9a9df43a577a6daf8844c0410ab15042f28a6d3e2eee4fc26f
6
+ metadata.gz: e4cc2ea0d61819436e922eacdcad551658deceac1b5a907cea03d306de65fa2f71b96018acf6fcc6f88163775cabf0ba9b8d6ded3e9067dfcf3cc3e70d3e3e6d
7
+ data.tar.gz: ca933647465baca8a294176a1fbbc336bf1956c8eebab2cf48dd45ac4e55ba55ea84b00d38cbdd9ee0cf012b332684b8902c5e98a8cbaaafbfc846b374a12801
data/CHANGELOG.md CHANGED
@@ -18,7 +18,7 @@ All notable changes to this project will be documented in this file.
18
18
  ### Added
19
19
  - Added C++ multithreading supports
20
20
  - Optimized old just present C++ code
21
- - Removed Png++ dependency in place of libspn
21
+ - Removed Png++ dependency in place of libspng
22
22
 
23
23
  ## [1.0.7] - 2026-01-10
24
24
  ### Added
@@ -76,3 +76,7 @@ All notable changes to this project will be documented in this file.
76
76
  ## [1.1.8] - 2026-04-19
77
77
  ### Changed
78
78
  - Treemap now available on multiprocessing side too.
79
+
80
+ ## [1.1.9] - 2026-04-24
81
+ ### Changed
82
+ - Improved the internal parts joining algorithm, which was imprecise in some circumstances.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- contrek (1.1.8)
4
+ contrek (1.1.9)
5
5
  chunky_png (~> 1.4)
6
6
  concurrent-ruby (~> 1.3.5)
7
7
  rice (= 4.5.0)
@@ -32,8 +32,6 @@ Node::Node(int min_x, int max_x, int y, NodeCluster* cluster, char name)
32
32
  this->track = 0;
33
33
  this->outer_index = -1;
34
34
  this->inner_index = -1;
35
- this->inner_left_index = -1;
36
- this->inner_right_index = -1;
37
35
  }
38
36
 
39
37
  bool Node::get_trackmax() {
@@ -280,7 +280,7 @@ void Cursor::traverse_inner(Part* act_part, std::vector<Part*>& all_parts, Bound
280
280
  int dest_part_versus = dest_part->versus();
281
281
  if (dest_part_versus != 0 && dest_part_versus == act_part->versus()) continue;
282
282
  if (dest_part->intersect_part(act_part)) {
283
- std::vector<EndPoint*> link_seq = duplicates_intersection(*dest_part, *act_part);
283
+ std::vector<EndPoint*> link_seq = dest_part->continuum_to(*act_part);
284
284
  if (!link_seq.empty()) {
285
285
  Part* ins_part = pool.acquire(Part::ADDED, act_part->polyline());
286
286
  for (EndPoint* pos : link_seq) {
@@ -314,33 +314,6 @@ void Cursor::traverse_inner(Part* act_part, std::vector<Part*>& all_parts, Bound
314
314
  }
315
315
  }
316
316
 
317
- template <typename T>
318
- std::vector<T*> difference_ptr(std::vector<T*>& a, std::vector<T*>& b)
319
- { std::vector<T*> result;
320
- for (T* item : a) {
321
- auto it = std::find_if(
322
- b.begin(), b.end(),
323
- [&](T* other) {
324
- return other == item;
325
- });
326
- if (it == b.end()) {
327
- result.push_back(item);
328
- }
329
- }
330
- return result;
331
- }
332
-
333
- std::vector<EndPoint*> Cursor::duplicates_intersection(Part& part_a, Part& part_b) {
334
- auto a1 = part_a.to_endpoints();
335
- auto b1 = part_b.to_endpoints();
336
- if (part_a.inverts) a1 = Part::remove_adjacent_pairs(a1);
337
- if (part_b.inverts) b1 = Part::remove_adjacent_pairs(b1);
338
- std::vector<EndPoint*> result = difference_ptr(a1, b1);
339
- std::vector<EndPoint*> temp = difference_ptr(b1, a1);
340
- result.insert(result.end(), temp.begin(), temp.end());
341
- return result;
342
- }
343
-
344
317
  std::vector<std::vector<Point*>> Cursor::combine(std::vector<std::vector<Point*>>& seqa, std::vector<std::vector<Point*>>& seqb)
345
318
  { std::vector<std::vector<Point*>> rets;
346
319
  size_t n = std::min(seqa.size(), seqb.size());
@@ -37,7 +37,6 @@ class Cursor {
37
37
  Sequence* outer_joined_polyline);
38
38
  std::vector<InnerPolyline*> collect_inner_sequences(Sequence* outer_seq);
39
39
  void traverse_inner(Part* act_part, std::vector<Part*> &all_parts, Bounds& bounds);
40
- std::vector<EndPoint*> duplicates_intersection(Part& part_a, Part& part_b);
41
40
  std::vector<std::vector<Point*>> combine(std::vector<std::vector<Point*>>& seqa, std::vector<std::vector<Point*>>& seqb);
42
41
  std::vector<Shape*> connect_missings(std::vector<Shape*> shapes_sequence, std::vector<Shape*> missing_shapes);
43
42
  };
@@ -74,29 +74,6 @@ bool Part::intersect_part(Part* other_part)
74
74
  return(intersect);
75
75
  }
76
76
 
77
- std::vector<EndPoint*> Part::to_endpoints() {
78
- std::vector<EndPoint*> out;
79
- QNode<Point>* current = head;
80
- while (current) {
81
- out.push_back((static_cast<Position*>(current))->end_point());
82
- current = current->next;
83
- }
84
- return out;
85
- }
86
-
87
- std::vector<EndPoint*> Part::remove_adjacent_pairs(const std::vector<EndPoint*>& input = {}) {
88
- std::vector<EndPoint*> result;
89
- result.reserve(input.size());
90
- for (EndPoint* current : input) {
91
- if (!result.empty() && result.back() == current) {
92
- result.pop_back();
93
- } else {
94
- result.push_back(current);
95
- }
96
- }
97
- return result;
98
- }
99
-
100
77
  void Part::orient()
101
78
  { if (this->size <= 1 || (this->size == 2 && this->inverts)) {
102
79
  this->versus_ = 0;
@@ -127,3 +104,41 @@ std::string Part::inspect() {
127
104
  ss << ")";
128
105
  return ss.str();
129
106
  }
107
+
108
+ std::vector<EndPoint*> Part::continuum_to(const Part& other_part) const {
109
+ if (this->size <= 2 && this->inverts && other_part.size <= 2 && other_part.inverts) return {};
110
+
111
+ Point* target = other_part.head->payload;
112
+ QNode<Point>* cursor = this->tail;
113
+
114
+ while (cursor != nullptr) {
115
+ if (*cursor->payload == *target) {
116
+ QNode<Point>* s = cursor;
117
+ QNode<Point>* o = other_part.head;
118
+ bool match = true;
119
+ int count = 0;
120
+
121
+ while (s != nullptr && o != nullptr) {
122
+ if (!(*s->payload == *o->payload)) {
123
+ match = false;
124
+ break;
125
+ }
126
+ s = s->next;
127
+ o = o->next;
128
+ count++;
129
+ }
130
+ if (match && s == nullptr) {
131
+ std::vector<EndPoint*> res;
132
+ res.reserve(count);
133
+ s = cursor;
134
+ for (int i = 0; i < count; ++i) {
135
+ res.push_back(static_cast<Position*>(s)->end_point());
136
+ s = s->next;
137
+ }
138
+ return res;
139
+ }
140
+ }
141
+ cursor = cursor->prev;
142
+ }
143
+ return {};
144
+ }
@@ -47,10 +47,9 @@ class Part : public Queueable<Point> {
47
47
  void touch();
48
48
  bool intersect_part(Part* other_part);
49
49
  void set_polyline(Polyline* polyline) { this->polyline_ = polyline; }
50
- std::vector<EndPoint*> to_endpoints();
51
- static std::vector<EndPoint*> remove_adjacent_pairs(const std::vector<EndPoint*>& input);
52
50
  void orient();
53
51
  std::string inspect();
52
+ std::vector<EndPoint*> continuum_to(const Part& other_part) const;
54
53
 
55
54
  private:
56
55
  int versus_ = 0;
@@ -195,9 +195,8 @@ module Contrek
195
195
  next if dest_part.trasmuted || dest_part.is?(Part::EXCLUSIVE)
196
196
  dest_part_versus = dest_part.versus
197
197
  next if dest_part_versus != 0 && dest_part_versus == act_part.versus
198
-
199
198
  if dest_part.intersect_part?(act_part)
200
- link_seq = duplicates_intersection(dest_part, act_part)
199
+ link_seq = dest_part.continuum_to?(act_part)
201
200
  if link_seq.any?
202
201
  ins_part = Part.new(Part::ADDED, act_part.polyline)
203
202
  link_seq.each do |pos|
@@ -221,17 +220,6 @@ module Contrek
221
220
  end
222
221
  # rubocop:enable Lint/NonLocalExitFromIterator
223
222
 
224
- # The sequences should contain inverted parts, e.g., 4,5,6,6,5,4. These parts must be
225
- # removed from the sequences, and the remaining elements are compared. Only the
226
- # elements that appear once between the two sequences are kept. This represents
227
- # a connection between parts inserted afterwards.
228
- # TODO evaluate the adoption of remove_adjacent_pairs!
229
- def duplicates_intersection(part_a, part_b)
230
- a1 = part_a.inverts ? Part.remove_adjacent_pairs(part_a.to_endpoints) : part_a.to_endpoints
231
- b1 = part_b.inverts ? Part.remove_adjacent_pairs(part_b.to_endpoints) : part_b.to_endpoints
232
- (a1 - b1) + (b1 - a1)
233
- end
234
-
235
223
  # example
236
224
  # a = [[A],[B,C]]
237
225
  # b = [[D],[E,F]]
@@ -81,10 +81,6 @@ module Contrek
81
81
  intersect
82
82
  end
83
83
 
84
- def to_endpoints
85
- map(&:end_point)
86
- end
87
-
88
84
  def orient!
89
85
  @versus = if size <= 1 || (size == 2 && @inverts)
90
86
  0
@@ -93,16 +89,34 @@ module Contrek
93
89
  end
94
90
  end
95
91
 
96
- def self.remove_adjacent_pairs(array = nil)
97
- n = array.size
98
- (0...(n - 1)).each do |i|
99
- if array[i] == array[i + 1]
100
- # Remove the pair and call recursively
101
- new_array = array[0...i] + array[(i + 2)..]
102
- return remove_adjacent_pairs(new_array)
92
+ def continuum_to?(other)
93
+ return [] if size <= 2 && inverts && other.size <= 2 && other.inverts
94
+ return [] if other.head.nil?
95
+
96
+ target = other.head.payload
97
+ cursor = tail
98
+ while cursor
99
+ if cursor.payload == target
100
+ s = cursor
101
+ o = other.head
102
+ match = true
103
+ nodes = []
104
+ while s && o
105
+ if s.payload != o.payload
106
+ match = false
107
+ break
108
+ end
109
+ nodes << s.end_point
110
+ s = s.next
111
+ o = o.next
112
+ end
113
+ if match && s.nil?
114
+ return nodes
115
+ end
103
116
  end
117
+ cursor = cursor.prev
104
118
  end
105
- array
119
+ []
106
120
  end
107
121
  end
108
122
  end
@@ -152,23 +152,6 @@ module Contrek
152
152
  def pop!
153
153
  rem(@tail)
154
154
  end
155
-
156
- def remove_adjacent_pairs!
157
- unless @tail.nil?
158
- pointer = @tail
159
- loop do
160
- break if pointer == @head
161
- if pointer.payload == pointer.prev&.payload
162
- later = pointer.next
163
- rem pointer.prev
164
- rem pointer
165
- pointer = later.nil? ? @tail : later
166
- redo
167
- end
168
- break unless (pointer = pointer.prev)
169
- end
170
- end
171
- end
172
155
  end
173
156
  end
174
157
  end
@@ -1,3 +1,3 @@
1
1
  module Contrek
2
- VERSION = "1.1.8"
2
+ VERSION = "1.1.9"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contrek
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.8
4
+ version: 1.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emanuele Cesaroni
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-19 00:00:00.000000000 Z
11
+ date: 2026-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec