contrek 1.3.5 → 1.3.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +5 -2
  5. data/ext/cpp_polygon_finder/PolygonFinder/src/ContrekApi.h +13 -17
  6. data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +78 -33
  7. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/FinderUtils.cpp +31 -101
  8. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/FinderUtils.h +2 -1
  9. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.cpp +1 -2
  10. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/OptionValue.h +91 -0
  11. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Options.h +123 -0
  12. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.cpp +4 -3
  13. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +14 -6
  14. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ClippedPolygonFinder.cpp +1 -1
  15. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ClippedPolygonFinder.h +2 -1
  16. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.cpp +19 -11
  17. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.h +5 -4
  18. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/GeoJsonStreamingMerger.h +4 -5
  19. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/HorizontalMerger.cpp +1 -1
  20. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/HorizontalMerger.h +1 -1
  21. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Merger.cpp +28 -2
  22. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Merger.h +3 -1
  23. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.cpp +12 -0
  24. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.h +2 -0
  25. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.cpp +16 -6
  26. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.h +2 -2
  27. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/SvgStreamingMerger.h +1 -1
  28. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.cpp +1 -13
  29. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.cpp +1 -1
  30. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.h +1 -1
  31. data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +66 -24
  32. data/lib/contrek/finder/concurrent/finder.rb +2 -2
  33. data/lib/contrek/finder/concurrent/geo_json_streaming_merger.rb +3 -3
  34. data/lib/contrek/finder/concurrent/merger.rb +17 -1
  35. data/lib/contrek/finder/concurrent/shape.rb +6 -0
  36. data/lib/contrek/finder/concurrent/streaming_merger.rb +8 -4
  37. data/lib/contrek/finder/concurrent/tile.rb +2 -7
  38. data/lib/contrek/finder/node_cluster.rb +1 -1
  39. data/lib/contrek/finder/polygon_finder.rb +2 -0
  40. data/lib/contrek/reducers/visvalingam_reducer.rb +2 -1
  41. data/lib/contrek/version.rb +1 -1
  42. metadata +4 -3
  43. data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/optionparser.h +0 -2858
@@ -10,6 +10,7 @@
10
10
  #include <gperftools/malloc_extension.h>
11
11
  #endif
12
12
  #include <iostream>
13
+ #include <cstdint>
13
14
  #include <list>
14
15
  #include <vector>
15
16
  #include <map>
@@ -61,6 +62,7 @@
61
62
  #include "PolygonFinder/src/polygon/finder/concurrent/Poolable.h"
62
63
  #include "PolygonFinder/src/polygon/finder/concurrent/Poolable.cpp"
63
64
  #include "PolygonFinder/src/polygon/finder/FinderUtils.h"
65
+ #include "PolygonFinder/src/polygon/finder/Options.h"
64
66
  #include "PolygonFinder/src/polygon/finder/FinderUtils.cpp"
65
67
  #include "PolygonFinder/src/polygon/finder/concurrent/ClippedPolygonFinder.h"
66
68
  #include "PolygonFinder/src/polygon/finder/concurrent/ClippedPolygonFinder.cpp"
@@ -119,56 +121,94 @@ using namespace Rice;
119
121
  namespace Rice::detail {
120
122
 
121
123
  template<>
122
- class From_Ruby<std::vector<std::string>*>
124
+ class From_Ruby<Options>
123
125
  { public:
124
126
  Convertible is_convertible(VALUE value)
125
127
  { switch (rb_type(value))
126
128
  { case RUBY_T_HASH:
129
+ case RUBY_T_NIL:
127
130
  return Convertible::Cast;
128
131
  break;
129
132
  default:
130
133
  return Convertible::None;
131
134
  }
132
135
  }
133
- std::vector<std::string>* convert(VALUE value)
134
- { std::vector<std::string> *arguments = new std::vector<std::string>();
135
- if (rb_type(value) == RUBY_T_NIL) return(arguments);
136
+ Options convert(VALUE value)
137
+ { Options options;
138
+ if (rb_type(value) == RUBY_T_NIL) return(options);
136
139
  Rice::Hash hash = (Rice::Hash) value;
137
140
  for (Rice::Hash::iterator it = hash.begin(); it != hash.end(); ++it) {
138
141
  Rice::String keyString = it->key.to_s();
139
142
  Rice::Object value = it->value;
140
143
  switch (value.rb_type()) {
141
144
  case T_STRING:
142
- arguments->push_back("--" + keyString.str()+"="+((Rice::String) value).str());
145
+ options[keyString.str()] = ((Rice::String) value).str();
143
146
  break;
144
147
  case T_SYMBOL:
145
- arguments->push_back("--" + keyString.str()+"="+((Rice::Symbol) value).str());
148
+ options[keyString.str()] = ::Identifier(((Rice::Symbol) value).str());
146
149
  break;
147
150
  case T_FLOAT:
148
- arguments->push_back("--" + keyString.str()+"="+std::to_string(NUM2DBL(value.value())));
151
+ options[keyString.str()] = NUM2DBL(value.value());
149
152
  break;
150
153
  case T_FIXNUM:
151
- arguments->push_back("--" + keyString.str()+"="+std::to_string(NUM2INT(value.value())));
154
+ case T_BIGNUM:
155
+ options[keyString.str()] = static_cast<std::int64_t>(NUM2LL(value.value()));
152
156
  break;
153
157
  case T_TRUE:
154
- arguments->push_back("--" + keyString.str()+"=true");
158
+ options[keyString.str()] = true;
155
159
  break;
156
160
  case T_FALSE:
157
- arguments->push_back("--" + keyString.str()+"=false");
161
+ options[keyString.str()] = false;
158
162
  break;
159
163
  case T_HASH:
160
- std::vector<std::string>* iv = From_Ruby<std::vector<std::string>*>::convert(value);
161
- for (std::vector<std::string>::iterator it_iv = iv->begin() ; it_iv != iv->end(); ++it_iv)
162
- { (*it_iv).replace(0, 2, "_");
163
- arguments->push_back("--" + keyString.str() + *it_iv);
164
- }
164
+ options[keyString.str()] = From_Ruby<Options>().convert(value.value());
165
+ break;
166
+ case T_NIL:
167
+ options[keyString.str()] = OptionValue();
168
+ break;
169
+ default:
170
+ rb_raise(rb_eTypeError,
171
+ "Unsupported option value type for '%s': %s",
172
+ keyString.str().c_str(),
173
+ rb_obj_classname(value.value()));
165
174
  break;
166
175
  }
167
176
  }
168
- return arguments;
177
+ return options;
169
178
  }
170
179
  };
171
180
 
181
+ Rice::Object option_value_to_ruby(const OptionValue& option_value);
182
+ Rice::Hash options_to_ruby(const Options& options) {
183
+ Rice::Hash hash;
184
+ for (const auto& [key, value] : options.values()) {
185
+ hash[Rice::Symbol(key)] = option_value_to_ruby(value);
186
+ }
187
+ return hash;
188
+ }
189
+
190
+ Rice::Object option_value_to_ruby(const OptionValue& option_value) {
191
+ if (option_value.is_bool()) {
192
+ return Rice::Object(option_value.as_bool() ? Qtrue : Qfalse);
193
+ }
194
+ if (option_value.is_integer()) {
195
+ return Rice::Object(LL2NUM(option_value.as_integer()));
196
+ }
197
+ if (option_value.is_double()) {
198
+ return Rice::Object(DBL2NUM(option_value.as_double()));
199
+ }
200
+ if (option_value.is_string()) {
201
+ return Rice::String(option_value.as_string());
202
+ }
203
+ if (option_value.is_identifier()) {
204
+ return Rice::Symbol(option_value.as_identifier().value);
205
+ }
206
+ if (option_value.is_options()) {
207
+ return options_to_ruby(option_value.as_options());
208
+ }
209
+ return Rice::Object(Qnil);
210
+ }
211
+
172
212
  template<>
173
213
  class To_Ruby<ProcessResult*>
174
214
  {public:
@@ -191,6 +231,7 @@ class To_Ruby<ProcessResult*>
191
231
  return_me[Symbol("width")] = pr->width;
192
232
  return_me[Symbol("height")] = pr->height;
193
233
  return_me[Symbol("versus")] = Symbol(pr->versus == Node::O ? "o" : "a");
234
+ return_me[Symbol("options")] = options_to_ruby(pr->options);
194
235
 
195
236
  Rice::Array out;
196
237
  for (Polygon& x : pr->polygons)
@@ -257,6 +298,7 @@ ProcessResult ruby_result_to_process_result(Rice::Object rb_result) {
257
298
  pr.width = detail::From_Ruby<int>().convert(metadata[Symbol("width")].value());
258
299
  pr.height = detail::From_Ruby<int>().convert(metadata[Symbol("height")].value());
259
300
  pr.versus = metadata[Symbol("versus")] == Symbol("o") ? Node::O : Node::A;
301
+ pr.options = detail::From_Ruby<Options>().convert(metadata[Symbol("options")].value());
260
302
 
261
303
  Rice::Array rb_polygons = rb_result.iv_get("@polygons_storage");
262
304
  for (size_t i = 0; i < rb_polygons.size(); ++i) {
@@ -316,7 +358,7 @@ struct OfstreamWrapper {
316
358
 
317
359
  SvgStreamingMerger* create_svg_streaming_merger(Object self,
318
360
  int number_of_threads,
319
- std::vector<std::string>* options,
361
+ Options options,
320
362
  Object stream_obj,
321
363
  int total_width,
322
364
  int total_height) {
@@ -326,11 +368,11 @@ SvgStreamingMerger* create_svg_streaming_merger(Object self,
326
368
 
327
369
  GeoJsonStreamingMerger* create_geo_json_streaming_merger(Object self,
328
370
  int number_of_threads,
329
- std::vector<std::string>* options,
371
+ Options options,
330
372
  Object stream_obj,
331
373
  int pixel_val) {
332
374
  OfstreamWrapper* wrapper = Rice::detail::From_Ruby<OfstreamWrapper*>().convert(stream_obj.value());
333
- return new GeoJsonStreamingMerger(number_of_threads, options, &wrapper->get_stream(),pixel_val);
375
+ return new GeoJsonStreamingMerger(number_of_threads, options, &wrapper->get_stream(), pixel_val);
334
376
  }
335
377
 
336
378
  OfstreamWrapper* create_ofstream(Object self, std::string path) {
@@ -409,18 +451,18 @@ void Init_cpp_polygon_finder() {
409
451
 
410
452
  Data_Type<PolygonFinder> rb_cPolygonFinder =
411
453
  define_class<PolygonFinder>("CPPPolygonFinder")
412
- .define_constructor(Constructor<PolygonFinder, Bitmap*, Matcher*, Bitmap*, std::vector<std::string>*>(), Arg("bitmap"), Arg("matcher"), Arg("test_bitmap") = nullptr, Arg("options") = nullptr, Rice::Arg("yield_gvl") = true)
454
+ .define_constructor(Constructor<PolygonFinder, Bitmap*, Matcher*, Bitmap*, Options>(), Arg("bitmap"), Arg("matcher"), Arg("test_bitmap") = nullptr, Arg("options") = Rice::Hash(), Rice::Arg("yield_gvl") = true)
413
455
  .define_method("get_shapelines", &PolygonFinder::get_shapelines)
414
456
  .define_method("process_info", &PolygonFinder::process_info, Rice::Arg("yield_gvl") = true);
415
457
 
416
458
  Data_Type<Finder> rb_cFinder =
417
459
  define_class<Finder>("CPPFinder")
418
- .define_constructor(Constructor<Finder, int, Bitmap*, Matcher*, std::vector<std::string>*>(), Arg("number_of_threads"), Arg("bitmap"), Arg("matcher"), Arg("options") = nullptr, Rice::Arg("yield_gvl") = true)
460
+ .define_constructor(Constructor<Finder, int, Bitmap*, Matcher*, Options>(), Arg("number_of_threads"), Arg("bitmap"), Arg("matcher"), Arg("options") = Rice::Hash(), Rice::Arg("yield_gvl") = true)
419
461
  .define_method("process_info", &Finder::process_info, Rice::Arg("yield_gvl") = true);
420
462
 
421
463
  Data_Type<Merger> rb_cMerger =
422
464
  define_class<Merger, Finder>("CPPMerger")
423
- .define_constructor(Constructor<Merger, int, std::vector<std::string>*>(), Arg("number_of_threads"), Arg("options") = nullptr, Rice::Arg("yield_gvl") = true)
465
+ .define_constructor(Constructor<Merger, int, Options>(), Arg("number_of_threads"), Arg("options") = Rice::Hash(), Rice::Arg("yield_gvl") = true)
424
466
  .define_method("add_tile", [](Merger& self, Object rb_result) {
425
467
  ProcessResult pr = Rice::detail::ruby_result_to_process_result(rb_result);
426
468
  self.add_tile(pr);
@@ -429,11 +471,11 @@ void Init_cpp_polygon_finder() {
429
471
 
430
472
  Data_Type<HorizontalMerger> rb_cHorizontalMerger =
431
473
  define_class<HorizontalMerger, Merger>("CPPHorizontalMerger")
432
- .define_constructor(Constructor<HorizontalMerger, int, std::vector<std::string>*>(), Arg("number_of_threads"), Arg("options") = nullptr, Arg("yield_gvl") = true);
474
+ .define_constructor(Constructor<HorizontalMerger, int, Options>(), Arg("number_of_threads"), Arg("options") = Rice::Hash(), Arg("yield_gvl") = true);
433
475
 
434
476
  Data_Type<VerticalMerger> rb_cVerticalMerger =
435
477
  define_class<VerticalMerger, Merger>("CPPVerticalMerger")
436
- .define_constructor(Constructor<VerticalMerger, int, std::vector<std::string>*>(), Arg("number_of_threads"), Arg("options") = nullptr, Arg("yield_gvl") = true)
478
+ .define_constructor(Constructor<VerticalMerger, int, Options>(), Arg("number_of_threads"), Arg("options") = Rice::Hash(), Arg("yield_gvl") = true)
437
479
  .define_method("add_tile", [](VerticalMerger& self, Object rb_result) {
438
480
  ProcessResult pr = Rice::detail::ruby_result_to_process_result(rb_result);
439
481
  self.add_tile(pr);
@@ -76,7 +76,6 @@ module Contrek
76
76
 
77
77
  def process_info
78
78
  raw_polygons = @whole_tile.to_raw_polygons
79
-
80
79
  compress_time = Benchmark.measure do
81
80
  if @options.has_key?(:compress)
82
81
  FakeCluster.new(raw_polygons, @options).compress_coords
@@ -94,7 +93,8 @@ module Contrek
94
93
  }.compact,
95
94
  width: @maximum_width,
96
95
  height: @height,
97
- versus: options[:versus]
96
+ versus: options[:versus],
97
+ options: options
98
98
  }
99
99
  metadata[:treemap] = @whole_tile.compute_treemap if options[:treemap]
100
100
  Contrek::Finder::Result.new(raw_polygons, metadata)
@@ -17,16 +17,16 @@ module Contrek
17
17
  @stream.write("]}")
18
18
  end
19
19
 
20
- def stream_raw_polygon(shape)
20
+ def stream_raw_polygon(polygon)
21
21
  if @first_feature
22
22
  @first_feature = false
23
23
  else
24
24
  @stream.write(",")
25
25
  end
26
- outer_ring = shape.outer_polyline.raw.map { |p| [p[:y], p[:x]] }
26
+ outer_ring = polygon[:outer].map { |p| [p[:y], p[:x]] }
27
27
  outer_ring << outer_ring.first if outer_ring.first != outer_ring.last
28
28
  polygon_coordinates = [outer_ring]
29
- shape.inner_polylines.map(&:raw).each do |sequence|
29
+ polygon[:inner].each do |sequence|
30
30
  inner_ring = sequence.map { |p| [p[:y], p[:x]] }
31
31
  inner_ring << inner_ring.first if inner_ring.first != inner_ring.last
32
32
  polygon_coordinates << inner_ring
@@ -11,12 +11,24 @@ module Contrek
11
11
  @current_x = 0
12
12
  @tiles = Queue.new
13
13
  @whole_tile = nil
14
- @options = options
14
+ @user_options = options
15
+ @options = {unsafe_mode: false}.merge(@user_options)
16
+ unless safe?
17
+ warn "[Contrek WARNING] Processing tile with 'unsafe_mode: true'. Incompatible result options might lead to unexpected vector geometry."
18
+ end
15
19
  end
16
20
 
17
21
  def add_tile(result)
18
22
  @height ||= result.metadata[:height]
23
+ raise ArgumentError, "All results must have the same height" if @height != result.metadata[:height] && safe?
19
24
  @options[:versus] ||= result.metadata[:versus]
25
+ raise ArgumentError, "All results must have the same versus option" if @options[:versus] != result.metadata[:versus] && safe?
26
+ if safe? && result.metadata[:options].key?(:compress)
27
+ if (result.metadata[:options][:compress].keys - [:uniq, :linear]).any?
28
+ raise ArgumentError, "Result with not supported postprocessing compression mode"
29
+ end
30
+ end
31
+
20
32
  end_x = @current_x + result.metadata[:width]
21
33
 
22
34
  tile = Tile.new(
@@ -32,6 +44,10 @@ module Contrek
32
44
  @current_x = end_x - 1
33
45
  end
34
46
 
47
+ def safe?
48
+ !@options[:unsafe_mode]
49
+ end
50
+
35
51
  def process_info
36
52
  process_tiles!(nil, height: @height)
37
53
  super
@@ -39,6 +39,12 @@ module Contrek
39
39
  def info
40
40
  "Shape (outer_polyline = #{outer_polyline.named}, children count = #{@children_shapes.size}"
41
41
  end
42
+
43
+ def to_raw_polygon(bounds: false)
44
+ {bounds: (outer_polyline.get_bounds if bounds),
45
+ outer: outer_polyline.raw,
46
+ inner: inner_polylines.map(&:raw)}.compact
47
+ end
42
48
  end
43
49
  end
44
50
  end
@@ -34,7 +34,11 @@ module Contrek
34
34
  bounds = shape.outer_polyline.get_bounds
35
35
  if flush || bounds[:max_x] < tile.end_x - 1
36
36
  @moved += 1
37
- stream_raw_polygon(shape)
37
+ polygon = shape.to_raw_polygon
38
+ if @options.has_key?(:compress)
39
+ FakeCluster.new([polygon], @options).compress_coords
40
+ end
41
+ stream_raw_polygon(polygon)
38
42
  false
39
43
  else
40
44
  true
@@ -44,10 +48,10 @@ module Contrek
44
48
  ensure_footer if flush
45
49
  end
46
50
 
47
- def stream_raw_polygon(shape)
48
- outer_pts = shape.outer_polyline.raw.map { |p| "#{p[:y]},#{p[:x]}" }.join(" ")
51
+ def stream_raw_polygon(polygon)
52
+ outer_pts = polygon[:outer].map { |p| "#{p[:y]},#{p[:x]}" }.join(" ")
49
53
  write_outer_polygon(outer_pts)
50
- shape.inner_polylines.map(&:raw).each do |sequence|
54
+ polygon[:inner].each do |sequence|
51
55
  inner_pts = sequence.map { |p| "#{p[:y]},#{p[:x]}" }.join(" ")
52
56
  write_inner_polygon(inner_pts)
53
57
  end
@@ -54,13 +54,8 @@ module Contrek
54
54
  end
55
55
 
56
56
  def to_raw_polygons
57
- @shapes.filter_map do |shape|
58
- unless shape.outer_polyline.empty?
59
- {bounds: (shape.outer_polyline.get_bounds if @finder.options[:bounds]),
60
- outer: shape.outer_polyline.raw,
61
- inner: shape.inner_polylines.map(&:raw)}.compact
62
- end
63
- end
57
+ bounds = @finder.options[:bounds]
58
+ @shapes.map { |s| s.to_raw_polygon(bounds:) }
64
59
  end
65
60
 
66
61
  def compute_treemap
@@ -33,7 +33,7 @@ module Contrek
33
33
  Contrek::Reducers::UniqReducer.new(points: seq).reduce! if @options[:compress].has_key?(:uniq)
34
34
  Contrek::Reducers::LinearReducer.new(points: seq, options: @options[:compress][:linear]).reduce! if @options[:compress].has_key?(:linear)
35
35
  Contrek::Reducers::RasterReducer.new(points: seq, options: @options).reduce! if @options[:compress].has_key?(:raster)
36
- Contrek::Reducers::VisvalingamReducer.new(points: seq, options: @options[:compress][:visvalingam]).reduce! if @options[:compress].has_key?(:visvalingam)
36
+ Contrek::Reducers::VisvalingamReducer.new(points: seq, options: @options[:compress]).reduce! if @options[:compress].has_key?(:visvalingam)
37
37
  Contrek::Reducers::DouglasPeuckerReducer.new(points: seq).reduce! if @options[:compress].has_key?(:douglas_peucker)
38
38
  end
39
39
  end
@@ -6,6 +6,7 @@ module Contrek
6
6
  module Finder
7
7
  class PolygonFinder
8
8
  def initialize(bitmap, matcher, test_bitmap = nil, options = {})
9
+ @ori_options = options
9
10
  @options = {versus: :a}.merge(options)
10
11
  sanitize_options
11
12
  @source_bitmap = bitmap
@@ -52,6 +53,7 @@ module Contrek
52
53
  width: @source_bitmap.w,
53
54
  height: @source_bitmap.h,
54
55
  treemap: (@node_cluster.treemap if @options.has_key?(:treemap)),
56
+ options: @ori_options,
55
57
  versus: @options[:versus]
56
58
  }
57
59
  Result.new(@node_cluster.polygons, metadata)
@@ -8,7 +8,8 @@ module Contrek
8
8
  class VisvalingamReducer < Reducer
9
9
  def initialize(points: list_of_points, options: {})
10
10
  @pts = points
11
- @tolerance = options[:tolerance] * options[:tolerance]
11
+ given_tolerance = options[:visvalingam_tolerance] || 10.0
12
+ @tolerance = given_tolerance * given_tolerance
12
13
  end
13
14
 
14
15
  def reduce!
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Contrek
4
- VERSION = "1.3.5"
4
+ VERSION = "1.3.6"
5
5
  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.3.5
4
+ version: 1.3.6
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-07-19 00:00:00.000000000 Z
11
+ date: 2026-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -183,6 +183,8 @@ files:
183
183
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.h
184
184
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.cpp
185
185
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.h
186
+ - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/OptionValue.h
187
+ - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Options.h
186
188
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PointPool.cpp
187
189
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PointPool.h
188
190
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Polygon.h
@@ -239,7 +241,6 @@ files:
239
241
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.h
240
242
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.cpp
241
243
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.h
242
- - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/optionparser.h
243
244
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/Matcher.cpp
244
245
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/Matcher.h
245
246
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/matchers/RGBMatcher.cpp