contrek 1.1.2 → 1.1.4

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +11 -1
  4. data/Gemfile.lock +1 -1
  5. data/LICENSE-MIT.md +9 -0
  6. data/README.md +58 -17
  7. data/contrek.gemspec +0 -1
  8. data/ext/cpp_polygon_finder/PolygonFinder/CMakeLists.txt +14 -2
  9. data/ext/cpp_polygon_finder/PolygonFinder/LICENSE_AGPL.txt +661 -0
  10. data/ext/cpp_polygon_finder/PolygonFinder/examples/example.cpp +9 -7
  11. data/ext/cpp_polygon_finder/PolygonFinder/src/ContrekApi.h +9 -0
  12. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/FastPngBitmap.cpp +4 -0
  13. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/FinderUtils.cpp +13 -2
  14. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/List.cpp +74 -82
  15. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/List.h +12 -4
  16. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Lists.cpp +0 -10
  17. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Lists.h +0 -7
  18. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.cpp +64 -46
  19. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.h +14 -23
  20. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.cpp +39 -44
  21. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.h +5 -7
  22. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.cpp +6 -4
  23. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +4 -3
  24. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.cpp +12 -4
  25. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/EndPoint.h +3 -2
  26. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.cpp +1 -0
  27. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.cpp +35 -2
  28. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.h +5 -1
  29. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.cpp +11 -11
  30. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.h +2 -1
  31. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +16 -2
  32. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +2 -0
  33. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.cpp +2 -5
  34. data/ext/cpp_polygon_finder/extconf.rb +12 -2
  35. data/lib/contrek/bitmaps/painting.rb +1 -0
  36. data/lib/contrek/finder/concurrent/cursor.rb +7 -5
  37. data/lib/contrek/finder/concurrent/finder.rb +2 -1
  38. data/lib/contrek/finder/concurrent/part.rb +12 -3
  39. data/lib/contrek/finder/concurrent/partitionable.rb +7 -5
  40. data/lib/contrek/finder/node.rb +61 -32
  41. data/lib/contrek/finder/node_cluster.rb +30 -27
  42. data/lib/contrek/finder/polygon_finder.rb +4 -4
  43. data/lib/contrek/version.rb +1 -1
  44. metadata +5 -4
@@ -106,8 +106,8 @@ module Contrek
106
106
 
107
107
  # rubocop:disable Lint/NonLocalExitFromIterator
108
108
  def traverse_outer(act_part, all_parts, shapes_sequence, outer_joined_polyline)
109
- all_parts << act_part if all_parts.last != act_part
110
-
109
+ last_part = all_parts.last
110
+ all_parts << act_part if last_part != act_part
111
111
  if act_part.is?(Part::EXCLUSIVE)
112
112
  return if act_part.size == 0
113
113
  while (position = act_part.next_position)
@@ -117,14 +117,14 @@ module Contrek
117
117
  outer_joined_polyline.add(position)
118
118
  end
119
119
  else
120
+ return if act_part.dead_end && all_parts.size > 1 && last_part.is?(Part::SEAM) && last_part.polyline == act_part.polyline
120
121
  while (new_position = act_part.iterator)
121
122
  return if outer_joined_polyline.size > 1 &&
122
123
  outer_joined_polyline.head.payload == new_position.payload &&
123
124
  act_part == all_parts.first
124
125
  outer_joined_polyline.add(Position.new(position: new_position.payload, hub: @cluster.hub))
125
-
126
126
  act_part.polyline.next_tile_eligible_shapes.each do |shape|
127
- if (part = shape.outer_polyline.find_first_part_by_position(new_position))
127
+ if (part = shape.outer_polyline.find_first_part_by_position(new_position, act_part.versus))
128
128
  if all_parts[-2] != part
129
129
  if all_parts.size >= 2
130
130
  map = all_parts[-2..].map(&:type).uniq
@@ -132,12 +132,12 @@ module Contrek
132
132
  end
133
133
  shapes_sequence.add(part.polyline.shape)
134
134
  part.next_position(new_position)
135
+ part.dead_end = true
135
136
  traverse_outer(part, all_parts, shapes_sequence, outer_joined_polyline)
136
137
  return
137
138
  end
138
139
  end
139
140
  end
140
- act_part.passes += 1
141
141
  act_part.next_position
142
142
  end
143
143
  end
@@ -189,6 +189,8 @@ module Contrek
189
189
  act_part.polyline.next_tile_eligible_shapes.each do |shape|
190
190
  shape.outer_polyline.parts.each do |dest_part|
191
191
  next if dest_part.trasmuted || dest_part.is?(Part::EXCLUSIVE)
192
+ dest_part_versus = dest_part.versus
193
+ next if dest_part_versus != 0 && dest_part_versus == act_part.versus
192
194
 
193
195
  if dest_part.intersect_part?(act_part)
194
196
  link_seq = duplicates_intersection(dest_part, act_part)
@@ -29,6 +29,7 @@ module Contrek
29
29
  @clusters = []
30
30
  @maximum_width = bitmap.w
31
31
  @number_of_tiles = options[:number_of_tiles] || (raise "number_of_tiles params is needed!")
32
+ @number_of_tiles = 1 if @number_of_tiles <= 0
32
33
 
33
34
  cw = @maximum_width.to_f / @number_of_tiles
34
35
  raise "One pixel tile width minimum!" if cw < 1.0
@@ -45,7 +46,7 @@ module Contrek
45
46
  finder = ClippedPolygonFinder.new(
46
47
  bitmap: bitmap,
47
48
  matcher: matcher,
48
- options: {versus: current_versus, bounds: true},
49
+ options: {versus: current_versus, bounds: true, connectivity: @options[:connectivity]}.compact,
49
50
  start_x: payload[:tile_start_x],
50
51
  end_x: payload[:tile_end_x]
51
52
  )
@@ -8,18 +8,19 @@ module Contrek
8
8
  ADDED = 2
9
9
 
10
10
  attr_reader :polyline, :index, :touched
11
- attr_accessor :next, :circular_next, :prev, :type, :passes, :inverts, :trasmuted, :delayed
11
+ attr_accessor :next, :circular_next, :prev, :type, :dead_end, :inverts, :trasmuted, :delayed, :versus
12
12
  def initialize(type, polyline)
13
13
  @type = type
14
14
  @polyline = polyline
15
15
  @next = nil
16
16
  @circular_next = nil
17
17
  @prev = nil
18
- @passes = 0
18
+ @dead_end = false
19
19
  @touched = false
20
20
  @inverts = false
21
21
  @trasmuted = false
22
22
  @delayed = false
23
+ @versus = 0
23
24
  end
24
25
 
25
26
  def is?(type)
@@ -60,7 +61,7 @@ module Contrek
60
61
  end
61
62
 
62
63
  def inspect
63
- "part #{polyline.parts.index(self)} (inv=#{@inverts} trm=#{@trasmuted} touched=#{@touched} passes=#{@passes}, #{size}x) of #{polyline.info} (#{name}) (#{to_a.map { |e| "[#{e[:x]},#{e[:y]}]" }.join})"
64
+ "part #{polyline.parts.index(self)} (versus=#{@versus} inv=#{@inverts} trm=#{@trasmuted} touched=#{@touched} dead_end =#{@dead_end}, #{size}x) of #{polyline.info} (#{name}) (#{to_a.map { |e| "[#{e[:x]},#{e[:y]}]" }.join})"
64
65
  end
65
66
 
66
67
  def innerable?
@@ -78,6 +79,14 @@ module Contrek
78
79
  map(&:end_point)
79
80
  end
80
81
 
82
+ def orient!
83
+ @versus = if size <= 1
84
+ 0
85
+ else
86
+ (tail.payload[:y] - head.payload[:y]).positive? ? 1 : -1
87
+ end
88
+ end
89
+
81
90
  def self.remove_adjacent_pairs(array = nil)
82
91
  n = array.size
83
92
  (0...(n - 1)).each do |i|
@@ -14,6 +14,8 @@ module Contrek
14
14
  last.next = last.circular_next = new_part if last
15
15
  new_part.circular_next = @parts.first
16
16
  new_part.prev = last
17
+
18
+ new_part.orient! if new_part.is?(Part::SEAM)
17
19
  end
18
20
 
19
21
  def insert_after(part, new_part)
@@ -25,10 +27,10 @@ module Contrek
25
27
  part.next = part.circular_next = new_part
26
28
  end
27
29
 
28
- def find_first_part_by_position(position)
30
+ def find_first_part_by_position(position, versus)
29
31
  @parts.find do |part|
30
32
  part.is?(Part::SEAM) &&
31
- part.passes == 0 &&
33
+ part.versus == -versus &&
32
34
  position.end_point.queues.include?(part)
33
35
  end
34
36
  end
@@ -144,10 +146,10 @@ module Contrek
144
146
 
145
147
  count = 0
146
148
  inside.each do |position|
147
- break unless position.end_point.queues.include?(inside_compare)
148
- count += 1
149
+ inclusion = position.end_point.queues.include?(inside_compare)
150
+ count += 1 if inclusion
149
151
  end
150
- if count == inside.size
152
+ if count == inside.size && count < inside_compare.size
151
153
  inside.type = Part::EXCLUSIVE
152
154
  inside.trasmuted = true
153
155
  break
@@ -3,7 +3,8 @@ module Contrek
3
3
  class Node
4
4
  include Listable
5
5
 
6
- attr_reader :min_x, :max_x, :y, :name, :tangs, :tangs_sequence, :tangs_count, :data_pointer
6
+ attr_reader :min_x, :max_x, :y, :name, :tangs_sequence, :tangs_count, :data_pointer,
7
+ :upper_start, :upper_end, :lower_start, :lower_end, :start_point, :end_point
7
8
  attr_accessor :track, :abs_x_index, :outer_index, :inner_index
8
9
 
9
10
  T_UP = -1
@@ -24,12 +25,11 @@ module Contrek
24
25
  OUTER = 0
25
26
  INNER = 1
26
27
 
27
- def initialize(cluster, min_x, max_x, y, name)
28
+ def initialize(cluster, min_x, max_x, y, name, connectivity_offset = 0)
28
29
  @name = name
29
30
  @min_x = min_x
30
31
  @max_x = max_x
31
32
  @y = y
32
- @tangs = {T_UP => [], T_DOWN => []}
33
33
  @tangs_sequence = nil
34
34
  @tangs_count = 0
35
35
  @track = 0
@@ -39,11 +39,23 @@ module Contrek
39
39
  @down_indexer = 0
40
40
  @outer_index = -1
41
41
  @inner_index = -1
42
- cluster.add_node(self)
42
+ @upper_start = Float::INFINITY
43
+ @upper_end = -1
44
+ @lower_start = Float::INFINITY
45
+ @lower_end = -1
46
+ @start_point = {x: min_x, y: y}
47
+ @end_point = {x: max_x, y: y}
48
+ @cluster = cluster
49
+ cluster.add_node(self, connectivity_offset)
43
50
  end
44
51
 
45
- def tangs?(node)
46
- @min_x <= node.max_x && node.min_x <= @max_x
52
+ def get_tangent_node_by_virtual_index(virtual_index)
53
+ return nil if virtual_index.nil?
54
+ if virtual_index < 0
55
+ @cluster.vert_nodes[y + T_UP][-(virtual_index + 1)]
56
+ else
57
+ @cluster.vert_nodes[y + T_DOWN][virtual_index]
58
+ end
47
59
  end
48
60
 
49
61
  def my_next(last, versus, mode)
@@ -62,15 +74,13 @@ module Contrek
62
74
  end
63
75
 
64
76
  when :inner
65
-
66
77
  if versus == :o
67
78
  (last_node_index == 0) ? last_node_index = tangs_sequence.size - 1 : last_node_index -= 1
68
79
  else
69
80
  (last_node_index == tangs_sequence.size - 1) ? last_node_index = 0 : last_node_index += 1
70
81
  end
71
-
72
82
  end
73
- tangs_sequence.at(last_node_index)
83
+ get_tangent_node_by_virtual_index(@tangs_sequence.at(last_node_index))
74
84
  end
75
85
 
76
86
  def coords_entering_to(enter_to, enter_mode, tracking)
@@ -79,14 +89,28 @@ module Contrek
79
89
  else
80
90
  @down_indexer - enter_to.abs_x_index
81
91
  end
82
- ds = tangs_sequence[enter_to_index]
83
- coords_source = ds.send(enter_mode)
84
- enter_to.track |= TURNER[tracking][coords_source[:m] - 1]
85
- coords_source[:point]
86
- end
87
92
 
88
- def tangs_with_x?(x)
89
- x.between?(@min_x, @max_x)
93
+ tg_index = @tangs_sequence[enter_to_index]
94
+ if tg_index < 0
95
+ node_up = @cluster.vert_nodes[y + T_UP][-(tg_index + 1)]
96
+ if enter_mode == :a
97
+ enter_to.track |= TURNER[tracking][OMAX - 1]
98
+ point = node_up.end_point
99
+ else
100
+ enter_to.track |= TURNER[tracking][OMIN - 1]
101
+ point = node_up.start_point
102
+ end
103
+ else
104
+ node_down = @cluster.vert_nodes[y + T_DOWN][tg_index]
105
+ if enter_mode == :a
106
+ enter_to.track |= TURNER[tracking][OMIN - 1]
107
+ point = node_down.start_point
108
+ else
109
+ enter_to.track |= TURNER[tracking][OMAX - 1]
110
+ point = node_down.end_point
111
+ end
112
+ end
113
+ point
90
114
  end
91
115
 
92
116
  def track_uncomplete
@@ -97,28 +121,33 @@ module Contrek
97
121
  (@track & OCOMPLETE) == OCOMPLETE
98
122
  end
99
123
 
100
- def add_intersection(other_node)
124
+ def add_intersection(other_node, other_node_index)
101
125
  if other_node.y < y
102
- @tangs[T_UP] << other_node
126
+ @upper_start = other_node_index if other_node_index < @upper_start
127
+ @upper_end = other_node_index if other_node_index > @upper_end
103
128
  else
104
- @tangs[T_DOWN] << other_node
129
+ @lower_start = other_node_index if other_node_index < @lower_start
130
+ @lower_end = other_node_index if other_node_index > @lower_end
105
131
  end
106
132
  end
107
133
 
108
- def precalc_tangs_sequences
109
- @tangs_sequence = Array.new(tangs[T_UP].size + tangs[T_DOWN].size)
110
- tangs = self.tangs[T_UP].sort_by(&:min_x)
111
- n = -1
112
- @up_indexer = -tangs[0].abs_x_index if tangs.size > 0
113
- tangs.each do |t_node|
114
- nd = Contrek::Finder::PolygonFinder::NodeDescriptor.new(t_node, {point: {x: t_node.max_x, y: t_node.y}, m: OMAX}, {point: {x: t_node.min_x, y: t_node.y}, m: OMIN})
115
- tangs_sequence[n += 1] = nd
134
+ def precalc_tangs_sequences(cluster:)
135
+ @tangs_sequence = []
136
+ @up_indexer = -cluster.vert_nodes[@y + T_UP][@upper_start].abs_x_index if @upper_end >= 0
137
+ if @upper_end >= 0
138
+ (@upper_start..@upper_end).each do |upper_pos|
139
+ @tangs_sequence << -(upper_pos + 1)
140
+ end
141
+ end
142
+ if @lower_end >= 0
143
+ lower_size = (@lower_end >= 0) ? (@lower_end - @lower_start + 1) : 0
144
+ upper_size = (@upper_end >= 0) ? (@upper_end - @upper_start + 1) : 0
145
+ @down_indexer = (cluster.vert_nodes[@y + T_DOWN][@lower_start].abs_x_index + lower_size + upper_size - 1)
116
146
  end
117
- tangs = self.tangs[T_DOWN].sort_by(&:min_x).reverse
118
- @down_indexer = (tangs.last.abs_x_index + self.tangs[T_DOWN].size + self.tangs[T_UP].size - 1) if tangs.size > 0
119
- tangs.each do |t_node|
120
- nd = Contrek::Finder::PolygonFinder::NodeDescriptor.new(t_node, {point: {x: t_node.min_x, y: t_node.y}, m: OMIN}, {point: {x: t_node.max_x, y: t_node.y}, m: OMAX})
121
- tangs_sequence[n += 1] = nd
147
+ if @lower_end >= 0
148
+ @lower_end.downto(@lower_start).each do |lower_pos|
149
+ @tangs_sequence << lower_pos
150
+ end
122
151
  end
123
152
  @tangs_count = tangs_sequence.size
124
153
  end
@@ -1,7 +1,7 @@
1
1
  module Contrek
2
2
  module Finder
3
3
  class NodeCluster
4
- attr_reader :root_nodes, :sequences, :polygons, :lists, :treemap, :vert_nodes
4
+ attr_reader :root_nodes, :sequences, :polygons, :lists, :treemap, :vert_nodes, :options
5
5
  VERSUS_INVERTER = {a: :o, o: :a}
6
6
 
7
7
  def initialize(h, options)
@@ -44,7 +44,7 @@ module Contrek
44
44
  def build_tangs_sequence
45
45
  @vert_nodes.each do |line|
46
46
  line.each do |node|
47
- node.precalc_tangs_sequences
47
+ node.precalc_tangs_sequences(cluster: self)
48
48
  end
49
49
  end
50
50
  end
@@ -62,21 +62,18 @@ module Contrek
62
62
  bounds = Bounds.empty
63
63
  # external polygon
64
64
  @plot_sequence << root_node
65
- next_node_nd = if versus == :a
66
- root_node.tangs_sequence.last
65
+
66
+ next_node = if versus == :a
67
+ root_node.get_tangent_node_by_virtual_index(root_node.tangs_sequence.last)
67
68
  else
68
- root_node.tangs_sequence.first
69
+ root_node.get_tangent_node_by_virtual_index(root_node.tangs_sequence.first)
69
70
  end
70
- #---------------
71
- if !next_node_nd.nil?
72
- next_node = next_node_nd.node
71
+ if !next_node.nil?
73
72
  coord = next_node.coords_entering_to(root_node, VERSUS_INVERTER[versus], Contrek::Finder::Node::OUTER)
74
73
  @sequence_coords << coord
75
74
  bounds.expand(x: coord[:x], y: coord[:y])
76
75
  end
77
- #---------------
78
-
79
- plot_node(next_node, root_node, bounds, versus) if @nodes > 0 && !next_node_nd.nil?
76
+ plot_node(next_node, root_node, bounds, versus) if @nodes > 0 && !next_node.nil?
80
77
 
81
78
  draw_sequence(bitmap, "X") unless bitmap.nil?
82
79
  @polygons << {outer: @sequence_coords, inner: [], bounds: (bounds.to_h if @options[:bounds])}.compact if @sequence_coords.size >= 2
@@ -103,9 +100,15 @@ module Contrek
103
100
  # end
104
101
 
105
102
  next_node = if (first.track & Contrek::Finder::Node::OMAX) != 0
106
- (inner_v == :a) ? first.tangs[Contrek::Finder::Node::T_UP].first : first.tangs[Contrek::Finder::Node::T_DOWN].first
103
+ if inner_v == :a
104
+ vert_nodes[first.y + Node::T_UP][first.upper_start]
105
+ else
106
+ vert_nodes[first.y + Node::T_DOWN][first.lower_start]
107
+ end
108
+ elsif inner_v == :a
109
+ vert_nodes[first.y + Node::T_DOWN][first.lower_end]
107
110
  else
108
- (inner_v == :a) ? first.tangs[Contrek::Finder::Node::T_DOWN].last : first.tangs[Contrek::Finder::Node::T_UP].last
111
+ vert_nodes[first.y + Node::T_UP][first.upper_end]
109
112
  end
110
113
 
111
114
  if !next_node.nil?
@@ -192,13 +195,13 @@ module Contrek
192
195
  @root_nodes.delete(node)
193
196
  @inner_plot.delete(node)
194
197
  last_node = @plot_sequence.last
195
- next_node_nd = node.my_next(last_node, versus, :inner)
196
- next_node = next_node_nd.node
198
+ next_node = node.my_next(last_node, versus, :inner)
197
199
  @plot_sequence << node
198
200
 
199
201
  plot = true
200
202
  if next_node.y == last_node.y
201
- plot = (node.tangs_sequence.send((versus == :a) ? :first : :last).node == next_node)
203
+ virtual_index = node.tangs_sequence.send((versus == :a) ? :first : :last)
204
+ plot = (node.get_tangent_node_by_virtual_index(virtual_index) == next_node)
202
205
  end
203
206
  if plot
204
207
  @sequence_coords << last_node.coords_entering_to(node, VERSUS_INVERTER[versus], Contrek::Finder::Node::INNER)
@@ -225,14 +228,14 @@ module Contrek
225
228
 
226
229
  node.outer_index = start_node.outer_index
227
230
  last_node = @plot_sequence.last
228
- next_node_nd = node.my_next(last_node, versus, :outer)
229
- next_node = next_node_nd.node
231
+ next_node = node.my_next(last_node, versus, :outer)
230
232
 
231
233
  @plot_sequence << node
232
234
 
233
235
  plot = true
234
236
  if next_node.y == last_node.y
235
- plot = (node.tangs_sequence.send((versus == :a) ? :last : :first).node == next_node)
237
+ virtual_index = node.tangs_sequence.send((versus == :a) ? :last : :first)
238
+ plot = (node.get_tangent_node_by_virtual_index(virtual_index) == next_node)
236
239
  end
237
240
 
238
241
  # coord
@@ -258,7 +261,7 @@ module Contrek
258
261
  plot_node(next_node, start_node, bounds, versus)
259
262
  end
260
263
 
261
- def add_node(node)
264
+ def add_node(node, offset)
262
265
  @nodes += 1
263
266
  node.abs_x_index = @vert_nodes[node.y].size
264
267
 
@@ -273,17 +276,17 @@ module Contrek
273
276
  index = 0
274
277
  loop do
275
278
  up_node = up_nodes[index]
276
- if up_node.max_x >= node.min_x
277
- if up_node.min_x <= node.max_x
278
- node.add_intersection(up_node)
279
- up_node.add_intersection(node)
279
+ if (up_node.max_x + offset) >= node.min_x
280
+ if (up_node.min_x - offset) <= node.max_x
281
+ node.add_intersection(up_node, index)
282
+ up_node.add_intersection(node, node.abs_x_index)
280
283
  end
281
284
  return if (index += 1) == up_nodes_count
282
285
  loop do
283
286
  up_node = up_nodes[index]
284
- if up_node.min_x <= node.max_x
285
- node.add_intersection(up_node)
286
- up_node.add_intersection(node)
287
+ if (up_node.min_x - offset) <= node.max_x
288
+ node.add_intersection(up_node, index)
289
+ up_node.add_intersection(node, node.abs_x_index)
287
290
  else
288
291
  return
289
292
  end
@@ -3,7 +3,6 @@ require "benchmark"
3
3
  module Contrek
4
4
  module Finder
5
5
  class PolygonFinder
6
- NodeDescriptor = Struct.new(:node, :a, :o)
7
6
  def initialize(bitmap, matcher, test_bitmap = nil, options = {})
8
7
  @options = {versus: :a}.merge(options)
9
8
  sanitize_options
@@ -91,6 +90,7 @@ module Contrek
91
90
 
92
91
  # image scan
93
92
  def scan
93
+ offset = (@node_cluster.options[:connectivity] == 8) ? 1 : 0
94
94
  last_color = nil
95
95
  matching = false
96
96
  min_x = start_x
@@ -103,16 +103,16 @@ module Contrek
103
103
  matching = true
104
104
  if x == (end_x - 1)
105
105
  max_x = x
106
- Contrek::Finder::Node.new(@node_cluster, min_x, max_x, y, last_color)
106
+ Contrek::Finder::Node.new(@node_cluster, min_x, max_x, y, last_color, offset)
107
107
  matching = false
108
108
  end
109
109
  elsif @matcher.unmatch?(color) && matching == true
110
110
  max_x = x - 1
111
- Contrek::Finder::Node.new(@node_cluster, min_x, max_x, y, last_color)
111
+ Contrek::Finder::Node.new(@node_cluster, min_x, max_x, y, last_color, offset)
112
112
  matching = false
113
113
  elsif x == (end_x - 1) && matching == true
114
114
  max_x = x
115
- Contrek::Finder::Node.new(@node_cluster, min_x, max_x, y, last_color)
115
+ Contrek::Finder::Node.new(@node_cluster, min_x, max_x, y, last_color, offset)
116
116
  matching = false
117
117
  end
118
118
  end
@@ -1,3 +1,3 @@
1
1
  module Contrek
2
- VERSION = "1.1.2"
2
+ VERSION = "1.1.4"
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.2
4
+ version: 1.1.4
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-02-09 00:00:00.000000000 Z
11
+ date: 2026-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -135,12 +135,14 @@ files:
135
135
  - CHANGELOG.md
136
136
  - Gemfile
137
137
  - Gemfile.lock
138
+ - LICENSE-MIT.md
138
139
  - LICENSE.md
139
140
  - README.md
140
141
  - Rakefile
141
142
  - contrek.gemspec
142
143
  - contrek.png
143
144
  - ext/cpp_polygon_finder/PolygonFinder/CMakeLists.txt
145
+ - ext/cpp_polygon_finder/PolygonFinder/LICENSE_AGPL.txt
144
146
  - ext/cpp_polygon_finder/PolygonFinder/examples/example.cpp
145
147
  - ext/cpp_polygon_finder/PolygonFinder/images/labyrinth.png
146
148
  - ext/cpp_polygon_finder/PolygonFinder/images/sample_10240x10240.png
@@ -275,7 +277,6 @@ licenses:
275
277
  - AGPL-3.0-only
276
278
  metadata:
277
279
  homepage_uri: https://github.com/runout77/contrek
278
- source_code_uri: https://github.com/runout77/contrek
279
280
  documentation_uri: https://github.com/runout77/contrek#readme
280
281
  changelog_uri: https://github.com/runout77/contrek/blob/main/CHANGELOG.md
281
282
  post_install_message:
@@ -293,7 +294,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
293
294
  - !ruby/object:Gem::Version
294
295
  version: '0'
295
296
  requirements: []
296
- rubygems_version: 3.4.1
297
+ rubygems_version: 3.5.22
297
298
  signing_key:
298
299
  specification_version: 4
299
300
  summary: Fast PNG contour tracing and shape detection for Ruby