contrek 1.3.1 → 1.3.3

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +3 -3
  5. data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +23 -3
  6. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/FastPngBitmap.cpp +2 -2
  7. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/RawBitmap.cpp +2 -2
  8. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/RemoteFastPngBitmap.cpp +1 -1
  9. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.h +2 -2
  10. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.h +4 -2
  11. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.cpp +6 -6
  12. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.cpp +16 -10
  13. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.h +1 -1
  14. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.cpp +16 -15
  15. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.h +3 -3
  16. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.cpp +1 -9
  17. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/GeoJsonStreamingMerger.h +80 -0
  18. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/InnerPolyline.cpp +9 -28
  19. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/InnerPolyline.h +10 -11
  20. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.h +7 -3
  21. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +4 -3
  22. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +7 -5
  23. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.cpp +1 -1
  24. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Queueable.h +2 -2
  25. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.cpp +0 -14
  26. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.h +0 -2
  27. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.cpp +5 -5
  28. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ShapePool.cpp +31 -26
  29. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ShapePool.h +7 -7
  30. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.cpp +14 -37
  31. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.h +11 -12
  32. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/SubPool.h +47 -0
  33. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/SvgStreamingMerger.h +56 -0
  34. data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +18 -3
  35. data/lib/contrek/cpp/cpp_geo_json_concurrent_streaming_merger.rb +11 -0
  36. data/lib/contrek/cpp/{cpp_concurrent_streaming_merger.rb → cpp_svg_concurrent_streaming_merger.rb} +1 -1
  37. data/lib/contrek/finder/concurrent/cluster.rb +6 -5
  38. data/lib/contrek/finder/concurrent/cursor.rb +2 -1
  39. data/lib/contrek/finder/concurrent/finder.rb +1 -12
  40. data/lib/contrek/finder/concurrent/geo_json_streaming_merger.rb +46 -0
  41. data/lib/contrek/finder/concurrent/inner_polyline.rb +8 -25
  42. data/lib/contrek/finder/concurrent/sequence.rb +1 -17
  43. data/lib/contrek/finder/concurrent/streaming_merger.rb +5 -27
  44. data/lib/contrek/finder/concurrent/svg_streaming_merger.rb +35 -0
  45. data/lib/contrek/version.rb +1 -1
  46. data/lib/contrek.rb +4 -1
  47. metadata +12 -6
@@ -5,7 +5,7 @@ module Contrek
5
5
  class Cluster
6
6
  attr_reader :tiles, :hub, :finder
7
7
 
8
- def initialize(finder:, height:, start_x:, end_x:)
8
+ def initialize(finder:, height:)
9
9
  @finder = finder
10
10
  @tiles = []
11
11
  @hub = Hub.new(height:)
@@ -57,23 +57,24 @@ module Contrek
57
57
  new_inners = shape.inner_polylines
58
58
  new_inner_polylines = []
59
59
  tot_inner += Benchmark.measure do
60
- new_inner_polylines = cursor.join_inners!(new_outer, treemap)
60
+ new_inner_polylines = cursor.join_inners!(treemap)
61
61
  new_inners += new_inner_polylines
62
62
  if treemap
63
63
  new_inner_polylines.each do |inner_polyline|
64
- inner_polyline.sequence.compute_vertical_bounds!
64
+ inner_polyline.compute_vertical_bounds!
65
65
  all_new_inner_polylines += new_inner_polylines
66
66
  end
67
67
  end
68
68
  new_inners += cursor.orphan_inners
69
69
  end.real
70
+ shape.clear_inner!
70
71
 
71
72
  polyline = Polyline.new(tile: tile, polygon: new_outer.to_a)
72
73
  inserting_new_shape = Shape.init_by(polyline, new_inners)
73
74
  new_shapes << inserting_new_shape
74
75
  polyline.shape = inserting_new_shape
75
76
 
76
- new_inner_polylines.each { |inner_polyline| inner_polyline.sequence.shape = inserting_new_shape }
77
+ new_inner_polylines.each { |inner_polyline| inner_polyline.shape = inserting_new_shape }
77
78
 
78
79
  if treemap
79
80
  cursor.shapes_sequence.each do |merged_shape|
@@ -115,7 +116,7 @@ module Contrek
115
116
  private
116
117
 
117
118
  def assign_ancestry(shape, inner_polyline)
118
- shape.set_parent_shape(inner_polyline.sequence.shape)
119
+ shape.set_parent_shape(inner_polyline.shape)
119
120
  shape.parent_inner_polyline = inner_polyline
120
121
  shape.fixed = true
121
122
  end
@@ -40,7 +40,7 @@ module Contrek
40
40
  outer_joined_polyline
41
41
  end
42
42
 
43
- def join_inners!(outer_seq, treemap)
43
+ def join_inners!(treemap)
44
44
  return_inner_polylines = []
45
45
  shape_index = 0
46
46
 
@@ -174,6 +174,7 @@ module Contrek
174
174
  if !dest_part.polyline.on?(Polyline::TRACKED_OUTER)
175
175
  @shapes_sequence << shape
176
176
  @orphan_inners += shape.inner_polylines
177
+ shape.clear_inner!
177
178
  end
178
179
  dest_part.polyline.turn_on(Polyline::TRACKED_OUTER)
179
180
  if !dest_part.touched
@@ -114,18 +114,7 @@ module Contrek
114
114
  return
115
115
  end
116
116
  if (twin_tile = arriving_tiles.find { |b| (b.start_x == (tile.end_x - 1)) || ((b.end_x - 1) == tile.start_x) })
117
-
118
- if twin_tile.start_x == (tile.end_x - 1)
119
- start_x = tile.start_x
120
- end_x = twin_tile.end_x
121
- else
122
- start_x = twin_tile.start_x
123
- end_x = tile.end_x
124
- end
125
-
126
- # puts "start = #{start_x} end = #{end_x}"
127
-
128
- cluster = Cluster.new(finder: self, height: height, start_x:, end_x:)
117
+ cluster = Cluster.new(finder: self, height: height)
129
118
  if twin_tile.start_x == (tile.end_x - 1)
130
119
  cluster.add(tile)
131
120
  cluster.add(twin_tile)
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Contrek
4
+ module Concurrent
5
+ class GeoJsonStreamingMerger < StreamingMerger
6
+ def initialize(stream_to:, pixel_val:, options: {})
7
+ @pixel_val = pixel_val
8
+ super(stream_to:, options:)
9
+ end
10
+
11
+ def write_header
12
+ @first_feature = true
13
+ @stream.write("{\"type\":\"FeatureCollection\",\"features\":[")
14
+ end
15
+
16
+ def write_footer
17
+ @stream.write("]}")
18
+ end
19
+
20
+ def stream_raw_polygon(shape)
21
+ if @first_feature
22
+ @first_feature = false
23
+ else
24
+ @stream.write(",")
25
+ end
26
+ outer_ring = shape.outer_polyline.raw.map { |p| [p[:y], p[:x]] }
27
+ outer_ring << outer_ring.first if outer_ring.first != outer_ring.last
28
+ polygon_coordinates = [outer_ring]
29
+ shape.inner_polylines.map(&:raw).each do |sequence|
30
+ inner_ring = sequence.map { |p| [p[:y], p[:x]] }
31
+ inner_ring << inner_ring.first if inner_ring.first != inner_ring.last
32
+ polygon_coordinates << inner_ring
33
+ end
34
+ feature_hash = {
35
+ type: "Feature",
36
+ properties: {PixelVal: @pixel_val},
37
+ geometry: {
38
+ type: "Polygon",
39
+ coordinates: polygon_coordinates
40
+ }
41
+ }
42
+ @stream.write(JSON.generate(feature_hash))
43
+ end
44
+ end
45
+ end
46
+ end
@@ -3,37 +3,20 @@
3
3
  module Contrek
4
4
  module Concurrent
5
5
  class InnerPolyline
6
- attr_reader :sequence
6
+ attr_reader :raw, :vertical_bounds
7
+ attr_accessor :shape
7
8
 
8
9
  def initialize(shape: nil, raw_coordinates: [], sequence: nil)
9
- @raw = raw_coordinates if raw_coordinates
10
- @sequence = sequence if sequence
11
- @shape = shape
12
- end
13
-
14
- def raw
15
- @sequence ? @sequence.to_a : @raw
16
- end
17
-
18
- def vertical_bounds
19
- if @sequence
20
- @sequence.vertical_bounds
10
+ if sequence
11
+ @shape = sequence.shape
12
+ @raw = sequence.to_a
21
13
  else
22
- raw_vertical_bounds
14
+ @shape = shape
15
+ @raw = raw_coordinates
23
16
  end
24
17
  end
25
18
 
26
- def shape
27
- if @sequence
28
- @sequence.shape
29
- else
30
- @shape
31
- end
32
- end
33
-
34
- private
35
-
36
- def raw_vertical_bounds
19
+ def compute_vertical_bounds!
37
20
  @vertical_bounds ||= begin
38
21
  min_y = Float::INFINITY
39
22
  max_y = 0
@@ -3,13 +3,9 @@
3
3
  module Contrek
4
4
  module Concurrent
5
5
  class Sequence
6
- attr_accessor :vertical_bounds, :shape
6
+ attr_accessor :shape
7
7
  prepend Queueable
8
8
 
9
- def initialize
10
- @vertical_bounds = nil
11
- end
12
-
13
9
  def is_not_vertical
14
10
  return false if size < 2
15
11
  x0 = head.payload[:x]
@@ -21,18 +17,6 @@ module Contrek
21
17
  false
22
18
  end
23
19
 
24
- def compute_vertical_bounds!
25
- return if size == 0
26
- min_y = Float::INFINITY
27
- max_y = 0
28
- get_vector_cache.each do |pos|
29
- y = pos[:y]
30
- min_y = y if y < min_y
31
- max_y = y if y > max_y
32
- end
33
- @vertical_bounds = {min: min_y, max: max_y}
34
- end
35
-
36
20
  def get_vector_cache
37
21
  @vector_cache ||= to_a
38
22
  end
@@ -3,10 +3,8 @@
3
3
  module Contrek
4
4
  module Concurrent
5
5
  class StreamingMerger < VerticalMerger
6
- def initialize(stream_to:, total_width:, total_height:, options: {})
6
+ def initialize(stream_to:, options: {})
7
7
  @stream = stream_to
8
- @total_width = total_width
9
- @total_height = total_height
10
8
  @moved = 0
11
9
  super(options: options)
12
10
  end
@@ -48,41 +46,21 @@ module Contrek
48
46
 
49
47
  def stream_raw_polygon(shape)
50
48
  outer_pts = shape.outer_polyline.raw.map { |p| "#{p[:y]},#{p[:x]}" }.join(" ")
51
- @stream.write(svg_outer_polygon(outer_pts))
49
+ write_outer_polygon(outer_pts)
52
50
  shape.inner_polylines.map(&:raw).each do |sequence|
53
51
  inner_pts = sequence.map { |p| "#{p[:y]},#{p[:x]}" }.join(" ")
54
- @stream.write(svg_inner_polygon(inner_pts))
52
+ write_inner_polygon(inner_pts)
55
53
  end
56
54
  end
57
55
 
58
56
  def ensure_header
59
57
  if @stream.pos == 0
60
- @stream.write(svg_header)
58
+ write_header
61
59
  end
62
60
  end
63
61
 
64
62
  def ensure_footer
65
- @stream.write(svg_footer)
66
- end
67
-
68
- def svg_footer
69
- "</svg>"
70
- end
71
-
72
- def svg_header
73
- "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"#{@total_width}\" height=\"#{@total_height}\"><style>#{svg_css}</style>"
74
- end
75
-
76
- def svg_outer_polygon(outer_pts)
77
- "<polygon points=\"#{outer_pts}\" class=\"out\"/>"
78
- end
79
-
80
- def svg_inner_polygon(inner_pts)
81
- "<polygon points=\"#{inner_pts}\" class=\"in\"/>"
82
- end
83
-
84
- def svg_css
85
- ".out{fill:none;stroke:red;stroke-width:1;}.in{fill:none;stroke:green;stroke-width:1;}.out:hover{stroke:yellow;}"
63
+ write_footer
86
64
  end
87
65
  end
88
66
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Contrek
4
+ module Concurrent
5
+ class SvgStreamingMerger < StreamingMerger
6
+ def initialize(stream_to:, total_width:, total_height:, options: {})
7
+ @total_width = total_width
8
+ @total_height = total_height
9
+ super(stream_to:, options:)
10
+ end
11
+
12
+ def write_header
13
+ @stream.write("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"#{@total_width}\" height=\"#{@total_height}\"><style>#{svg_css}</style>")
14
+ end
15
+
16
+ def write_footer
17
+ @stream.write("</svg>")
18
+ end
19
+
20
+ def write_outer_polygon(outer_pts)
21
+ @stream.write("<polygon points=\"#{outer_pts}\" class=\"out\"/>")
22
+ end
23
+
24
+ def write_inner_polygon(inner_pts)
25
+ @stream.write("<polygon points=\"#{inner_pts}\" class=\"in\"/>")
26
+ end
27
+
28
+ private
29
+
30
+ def svg_css
31
+ ".out{fill:none;stroke:red;stroke-width:1;}.in{fill:none;stroke:green;stroke-width:1;}.out:hover{stroke:yellow;}"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Contrek
4
- VERSION = "1.3.1"
4
+ VERSION = "1.3.3"
5
5
  end
data/lib/contrek.rb CHANGED
@@ -40,6 +40,8 @@ require "contrek/finder/concurrent/merger"
40
40
  require "contrek/finder/concurrent/horizontal_merger"
41
41
  require "contrek/finder/concurrent/vertical_merger"
42
42
  require "contrek/finder/concurrent/streaming_merger"
43
+ require "contrek/finder/concurrent/svg_streaming_merger"
44
+ require "contrek/finder/concurrent/geo_json_streaming_merger"
43
45
  require "contrek/finder/concurrent/cursor"
44
46
  require "contrek/map/mercator_projection"
45
47
  require "contrek/matchers/matcher"
@@ -54,7 +56,8 @@ require "contrek/cpp/cpp_concurrent_finder"
54
56
  require "contrek/cpp/cpp_concurrent_merger"
55
57
  require "contrek/cpp/cpp_concurrent_horizontal_merger"
56
58
  require "contrek/cpp/cpp_concurrent_vertical_merger"
57
- require "contrek/cpp/cpp_concurrent_streaming_merger"
59
+ require "contrek/cpp/cpp_svg_concurrent_streaming_merger"
60
+ require "contrek/cpp/cpp_geo_json_concurrent_streaming_merger"
58
61
  require "contrek/cpp/cpp_tempfile"
59
62
  require "contrek/cpp/cpp_result"
60
63
 
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.3.1
4
+ version: 1.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emanuele Cesaroni
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-06-20 00:00:00.000000000 Z
11
+ date: 2026-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -188,6 +188,7 @@ files:
188
188
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/FakeCluster.h
189
189
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.cpp
190
190
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.h
191
+ - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/GeoJsonStreamingMerger.h
191
192
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/HorizontalMerger.cpp
192
193
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/HorizontalMerger.h
193
194
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Hub.cpp
@@ -218,6 +219,8 @@ files:
218
219
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ShapePool.h
219
220
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.cpp
220
221
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.h
222
+ - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/SubPool.h
223
+ - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/SvgStreamingMerger.h
221
224
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.cpp
222
225
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.h
223
226
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.cpp
@@ -254,9 +257,10 @@ files:
254
257
  - lib/contrek/cpp/cpp_concurrent_finder.rb
255
258
  - lib/contrek/cpp/cpp_concurrent_horizontal_merger.rb
256
259
  - lib/contrek/cpp/cpp_concurrent_merger.rb
257
- - lib/contrek/cpp/cpp_concurrent_streaming_merger.rb
258
260
  - lib/contrek/cpp/cpp_concurrent_vertical_merger.rb
261
+ - lib/contrek/cpp/cpp_geo_json_concurrent_streaming_merger.rb
259
262
  - lib/contrek/cpp/cpp_result.rb
263
+ - lib/contrek/cpp/cpp_svg_concurrent_streaming_merger.rb
260
264
  - lib/contrek/cpp/cpp_tempfile.rb
261
265
  - lib/contrek/finder/bounds.rb
262
266
  - lib/contrek/finder/concurrent/clipped_polygon_finder.rb
@@ -265,6 +269,7 @@ files:
265
269
  - lib/contrek/finder/concurrent/end_point.rb
266
270
  - lib/contrek/finder/concurrent/fake_cluster.rb
267
271
  - lib/contrek/finder/concurrent/finder.rb
272
+ - lib/contrek/finder/concurrent/geo_json_streaming_merger.rb
268
273
  - lib/contrek/finder/concurrent/horizontal_merger.rb
269
274
  - lib/contrek/finder/concurrent/hub.rb
270
275
  - lib/contrek/finder/concurrent/inner_polyline.rb
@@ -279,6 +284,7 @@ files:
279
284
  - lib/contrek/finder/concurrent/sequence.rb
280
285
  - lib/contrek/finder/concurrent/shape.rb
281
286
  - lib/contrek/finder/concurrent/streaming_merger.rb
287
+ - lib/contrek/finder/concurrent/svg_streaming_merger.rb
282
288
  - lib/contrek/finder/concurrent/tile.rb
283
289
  - lib/contrek/finder/concurrent/vertical_merger.rb
284
290
  - lib/contrek/finder/list.rb
@@ -307,7 +313,7 @@ metadata:
307
313
  homepage_uri: https://github.com/runout77/contrek
308
314
  documentation_uri: https://github.com/runout77/contrek#readme
309
315
  changelog_uri: https://github.com/runout77/contrek/blob/main/CHANGELOG.md
310
- post_install_message:
316
+ post_install_message:
311
317
  rdoc_options: []
312
318
  require_paths:
313
319
  - lib
@@ -323,7 +329,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
323
329
  version: '0'
324
330
  requirements: []
325
331
  rubygems_version: 3.5.22
326
- signing_key:
332
+ signing_key:
327
333
  specification_version: 4
328
334
  summary: Fast PNG contour tracing and shape detection for Ruby
329
335
  test_files: []