contrek 1.4.5 → 1.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9350d60698a69dda805ede85e42b80fcc38022a361e52674fd2780d696e0f9ff
4
- data.tar.gz: '08d164d2e53bb3c96e7212ac6bc9d46bb673de8f10bb950d43f3d66d0c86d793'
3
+ metadata.gz: a6ed7af7c2661396d55b6ddacd89dfc6c08c4c54744d1443d03a6ba533605ed4
4
+ data.tar.gz: 3308bedea2f5e89fe8031a65c404c250490542142101dba32fd09f8510cb8cfb
5
5
  SHA512:
6
- metadata.gz: 1c6d0b73ab8affa0ed17aa3fd803f7aed81cec846db6edd3de5dfcec8103bf23c9e23484819c4a981a4cb0c46da18f0b169122124213a9b4417df108f54c468a
7
- data.tar.gz: 57817011679288782915a50ca1adf4155b71732ab73e330e2ac696ea504d7204c08935a6b83487000faac68b37f38aff5b5761d78fc85aab7703752f2700d65f
6
+ metadata.gz: 250b0ed1bce589beaae764e03226206853f9e9c3bb356fe3bf827cd25c69d72f33ad820f3afa5d9d31aa83e628e67dd8c4500782dcdb668f44b0e098932f6c4f
7
+ data.tar.gz: 7cf17a172afd9ec9b1788f2abe1779421d204886b99fd54e4729fbf9b616cc3968bb7586cafa5b17da6b5cbcf9641e3f210ee6d3d320e4be67e945022964af13
data/CHANGELOG.md CHANGED
@@ -170,3 +170,6 @@ All notable changes to this project will be documented in this file.
170
170
 
171
171
  ## [1.4.5] - 2026-10-11
172
172
  - Added tile boundary validation for external geometries, with support for bypassing checks via `unsafe_mode: true`.
173
+
174
+ ## [1.4.6] - 2026-10-18
175
+ - Added tile metadata, polygon bounds, ordering, and shared boundary validation for Ruby and C++ mergers, with `unsafe_mode: true` to bypass validation.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- contrek (1.4.5)
4
+ contrek (1.4.6)
5
5
  chunky_png (~> 1.4)
6
6
  concurrent-ruby (~> 1.3.5)
7
7
  ffi (~> 1.17)
data/README.md CHANGED
@@ -726,17 +726,13 @@ extractors, provided that the input geometry follows the requirements below.
726
726
 
727
727
  ### Boundary Validation
728
728
 
729
- By default, Contrek validates the shared boundaries of adjacent tiles when
730
- merging externally supplied geometries. Boundary coordinates must match
731
- exactly, including intermediate vertices. Otherwise, the merger raises a
732
- `Tile boundary mismatch` error.
729
+ By default, Contrek validates the shared boundaries of adjacent tiles when merging externally supplied geometries. Boundary coordinates must match exactly, including intermediate vertices. Otherwise, the merger raises a `Tile boundary mismatch` error.
733
730
 
734
- This validation can be disabled by setting `unsafe_mode: true`, avoiding
735
- validation overhead when the input geometries are known to be valid.
731
+ This validation can be disabled by setting `unsafe_mode: true`, avoiding validation overhead when the input geometries are known to be valid.
736
732
 
737
- **Important:** Boundary validation does not verify all the Laws of the Tiles.
738
- Users supplying external geometries remain responsible for satisfying every
739
- requirement listed above.
733
+ **Important:** Boundary validation does not verify all the Laws of the Tiles. Users supplying external geometries remain responsible for satisfying every requirement listed above.
734
+
735
+ **Important:** Boundary validation prioritizes correctness over performance and introduce additional processing overhead. Experienced users who can guarantee that their input geometries satisfy the Laws of the Tiles can enable `unsafe_mode: true` to bypass validation entirely and achieve maximum merging performance. This option can also be useful during debugging to isolate merging issues from validation errors.
740
736
 
741
737
  # Results
742
738
 
@@ -413,7 +413,7 @@ void stream_progressive_png_image(const std::string& filepath, uint32_t stripe_h
413
413
 
414
414
  SvgStreamingMerger merger(
415
415
  0,
416
- {{"bounds", true},{"unsafe_mode", true}},
416
+ {{"bounds", true}, {"unsafe_mode", true}},
417
417
  &stream,
418
418
  source.width(),
419
419
  source.height());
@@ -68,7 +68,8 @@ struct pf_Options {
68
68
 
69
69
  struct ProcessResult {
70
70
  int groups;
71
- int width, height;
71
+ int width = 0;
72
+ int height = 0;
72
73
  int versus;
73
74
  int number_of_threads;
74
75
  bool has_bounds = false;
@@ -12,6 +12,7 @@
12
12
  #include <vector>
13
13
  #include <algorithm>
14
14
  #include <list>
15
+ #include <memory>
15
16
  #include "Merger.h"
16
17
 
17
18
  Merger::Merger(int number_of_threads, const Options& options)
@@ -19,7 +20,9 @@ Merger::Merger(int number_of_threads, const Options& options)
19
20
  if (options.contains("versus")) {
20
21
  std::cerr << "[Contrek WARNING] The given options 'versus' will be ignored." << std::endl;
21
22
  }
22
- if (!this->safe()) {
23
+ if (safe()) {
24
+ validator_ = std::make_unique<MergerValidator>(*this);
25
+ } else {
23
26
  std::cerr << "[Contrek WARNING] Processing tile with 'unsafe_mode: true'. "
24
27
  << "Incompatible result options might lead to unexpected vector geometry.\n";
25
28
  }
@@ -30,7 +33,10 @@ bool Merger::safe() {
30
33
  }
31
34
 
32
35
  void Merger::add_tile(ProcessResult& result)
33
- { if (this->height == 0) {
36
+ { if (validator_) {
37
+ validator_->validate_metadata(result);
38
+ }
39
+ if (this->height == 0) {
34
40
  this->height = result.height;
35
41
  } else {
36
42
  if (result.height != this->height && safe()) {
@@ -51,17 +57,15 @@ void Merger::add_tile(ProcessResult& result)
51
57
  }
52
58
  }
53
59
  }
54
- if (safe()) validate(result);
55
60
 
56
61
  int end_x = this->current_x + result.width;
62
+ if (validator_) {
63
+ validator_->validate(result, this->current_x, end_x);
64
+ }
57
65
  Tile* tile = new Tile(this, this->current_x, end_x, std::to_string(tiles_.size()), tiles_.size(), Benchmarks {0, 0});
58
66
  tile->assign_raw_polygons(result.polygons, result.treemap);
59
67
  tiles_.queue_push(tile);
60
68
 
61
- if (safe()) {
62
- previous_boundary_ = boundary_coordinates(result.polygons, end_x);
63
- }
64
-
65
69
  this->maximum_width_ = end_x;
66
70
  this->current_x = end_x - 1;
67
71
  }
@@ -84,26 +88,3 @@ void Merger::translate(ProcessResult& result, int offset) {
84
88
  }
85
89
  }
86
90
 
87
- std::vector<int> Merger::boundary_coordinates(const std::list<Polygon>& polygons, int boundary_x) {
88
- std::vector<int> coordinates;
89
-
90
- for (const auto& polygon : polygons) {
91
- for (const auto& point : polygon.outer) {
92
- if (point.x == boundary_x) {
93
- coordinates.push_back(point.y);
94
- }
95
- }
96
- }
97
-
98
- std::sort(coordinates.begin(), coordinates.end());
99
- return coordinates;
100
- }
101
-
102
- void Merger::validate(const ProcessResult& result) {
103
- if (tiles_.size() == 0) return;
104
-
105
- const auto current = boundary_coordinates(result.polygons, current_x);
106
- if (previous_boundary_ != current) {
107
- throw std::invalid_argument("Tile boundary mismatch: adjacent tiles have different edge coordinates");
108
- }
109
- }
@@ -11,7 +11,9 @@
11
11
  #include <string>
12
12
  #include <vector>
13
13
  #include <list>
14
+ #include <memory>
14
15
  #include "Finder.h"
16
+ #include "MergerValidator.h"
15
17
  #include "../Options.h"
16
18
 
17
19
  class Merger : public Finder {
@@ -24,7 +26,5 @@ class Merger : public Finder {
24
26
  protected:
25
27
  void translate(ProcessResult& result, int offset);
26
28
  int current_x = 0;
27
- void validate(const ProcessResult& result);
28
- static std::vector<int> boundary_coordinates(const std::list<Polygon>& polygons, int boundary_x);
29
- std::vector<int> previous_boundary_;
29
+ std::unique_ptr<MergerValidator> validator_;
30
30
  };
@@ -0,0 +1,104 @@
1
+ /*
2
+ * MergerValidator.cpp
3
+ *
4
+ * Copyright (c) 2025-2026 Emanuele Cesaroni
5
+ *
6
+ * Licensed under the GNU Affero General Public License v3 (AGPLv3).
7
+ * See the LICENSE file in this directory for the full license text.
8
+ */
9
+
10
+ #include "MergerValidator.h"
11
+ #include "Merger.h"
12
+ #include <algorithm>
13
+ #include <stdexcept>
14
+ #include <vector>
15
+ #include <list>
16
+ #include <utility>
17
+
18
+ MergerValidator::MergerValidator(const Merger& merger)
19
+ : merger_(merger) {}
20
+
21
+ void MergerValidator::validate_metadata(const ProcessResult& result) const {
22
+ if (result.width <= 0) {
23
+ throw std::invalid_argument("Invalid result metadata: width must be a positive integer");
24
+ }
25
+ if (result.height <= 0) {
26
+ throw std::invalid_argument("Invalid result metadata: height must be a positive integer");
27
+ }
28
+ if (result.versus != Node::A && result.versus != Node::O) {
29
+ throw std::invalid_argument("Invalid result metadata: unsupported versus option");
30
+ }
31
+ }
32
+
33
+ void MergerValidator::validate(const ProcessResult& result, int start_x, int end_x) {
34
+ validate_bounds(result.polygons);
35
+ validate_polygon_order(result.polygons);
36
+ validate_boundary(result, start_x);
37
+
38
+ previous_boundary_ = boundary_coordinates(result.polygons, end_x);
39
+ has_previous_boundary_ = true;
40
+ }
41
+
42
+ void MergerValidator::validate_bounds(const std::list<Polygon>& polygons) const {
43
+ for (const auto& polygon : polygons) {
44
+ if (polygon.outer.empty()) {
45
+ throw std::invalid_argument("Invalid polygon: empty outer contour");
46
+ }
47
+ RectBounds actual = RectBounds::empty();
48
+
49
+ for (const auto& point : polygon.outer) {
50
+ actual.expand(point.x, point.y);
51
+ }
52
+
53
+ const auto& bounds = polygon.bounds;
54
+ if (bounds.min_x != actual.min_x ||
55
+ bounds.max_x != actual.max_x ||
56
+ bounds.min_y != actual.min_y ||
57
+ bounds.max_y != actual.max_y) {
58
+ throw std::invalid_argument("Invalid polygon bounds: bounding box does not match outer contour");
59
+ }
60
+ }
61
+ }
62
+
63
+ void MergerValidator::validate_polygon_order(const std::list<Polygon>& polygons) const {
64
+ bool has_previous = false;
65
+ std::pair<int, int> previous;
66
+
67
+ for (const auto& polygon : polygons) {
68
+ const auto& bounds = polygon.bounds;
69
+
70
+ const std::pair<int, int> current = merger_.transpose()
71
+ ? std::make_pair(bounds.min_x, bounds.min_y)
72
+ : std::make_pair(bounds.min_y, bounds.min_x);
73
+
74
+ if (has_previous && current < previous) {
75
+ throw std::invalid_argument("Invalid polygon order: polygons are not in raster scan order");
76
+ }
77
+ previous = current;
78
+ has_previous = true;
79
+ }
80
+ }
81
+
82
+ void MergerValidator::validate_boundary(const ProcessResult& result, int start_x) const {
83
+ if (!has_previous_boundary_) return;
84
+
85
+ const auto current = boundary_coordinates(result.polygons, start_x);
86
+ if (previous_boundary_ != current) {
87
+ throw std::invalid_argument("Tile boundary mismatch: adjacent tiles have different edge coordinates");
88
+ }
89
+ }
90
+
91
+ std::vector<int> MergerValidator::boundary_coordinates(const std::list<Polygon>& polygons, int boundary_x) {
92
+ std::vector<int> coordinates;
93
+
94
+ for (const auto& polygon : polygons) {
95
+ for (const auto& point : polygon.outer) {
96
+ if (point.x == boundary_x) {
97
+ coordinates.push_back(point.y);
98
+ }
99
+ }
100
+ }
101
+
102
+ std::sort(coordinates.begin(), coordinates.end());
103
+ return coordinates;
104
+ }
@@ -0,0 +1,35 @@
1
+ /*
2
+ * MergerValidator.h
3
+ *
4
+ * Copyright (c) 2025-2026 Emanuele Cesaroni
5
+ *
6
+ * Licensed under the GNU Affero General Public License v3 (AGPLv3).
7
+ * See the LICENSE file in this directory for the full license text.
8
+ */
9
+
10
+ #pragma once
11
+
12
+ #include <vector>
13
+ #include <list>
14
+ #include "../PolygonFinder.h"
15
+
16
+ class Merger;
17
+
18
+ class MergerValidator {
19
+ public:
20
+ explicit MergerValidator(const Merger& merger);
21
+
22
+ void validate_metadata(const ProcessResult& result) const;
23
+ void validate(const ProcessResult& result, int start_x, int end_x);
24
+
25
+ private:
26
+ const Merger& merger_;
27
+ std::vector<int> previous_boundary_;
28
+ bool has_previous_boundary_ = false;
29
+
30
+ void validate_bounds(const std::list<Polygon>& polygons) const;
31
+ void validate_polygon_order(const std::list<Polygon>& polygons) const;
32
+ void validate_boundary(const ProcessResult& result, int start_x) const;
33
+
34
+ static std::vector<int> boundary_coordinates(const std::list<Polygon>& polygons, int boundary_x);
35
+ };
@@ -60,27 +60,25 @@ void Tile::assign_raw_polygons(const std::list<Polygon>& raw_polylines, const st
60
60
  std::unordered_map<int, Shape*> shapes_map;
61
61
  int polyline_index = 0;
62
62
  for (const auto& raw_polyline : raw_polylines)
63
- { if (raw_polyline.bounds.width() > 0)
64
- { Polyline* polyline = this->shapes_pool->acquire_polyline(this, raw_polyline.outer, raw_polyline.bounds);
65
- std::vector<InnerPolyline*> inner_polylines_list;
66
- for (auto& raw_points : raw_polyline.inner) {
67
- inner_polylines_list.push_back(this->shapes_pool->acquire_inner_polyline(raw_points, nullptr));
68
- }
69
- Shape* shape = this->shapes_pool->acquire_shape(polyline, inner_polylines_list);
70
- polyline->shape = shape;
71
- this->shapes_.push_back(shape);
72
-
73
- if (treemap.size() > 0)
74
- { auto treemap_entry = treemap[polyline_index];
75
- shapes_map[polyline_index] = shape;
76
- if (treemap_entry.first != -1 && treemap_entry.second != -1) {
77
- auto it = shapes_map.find(treemap_entry.first);
78
- if (it != shapes_map.end()) {
79
- Shape* parent = it->second;
80
- shape->set_parent_shape(parent);
81
- shape->fixed = true;
82
- shape->parent_inner_polyline = parent->inner_polylines[treemap_entry.second];
83
- }
63
+ { Polyline* polyline = this->shapes_pool->acquire_polyline(this, raw_polyline.outer, raw_polyline.bounds);
64
+ std::vector<InnerPolyline*> inner_polylines_list;
65
+ for (auto& raw_points : raw_polyline.inner) {
66
+ inner_polylines_list.push_back(this->shapes_pool->acquire_inner_polyline(raw_points, nullptr));
67
+ }
68
+ Shape* shape = this->shapes_pool->acquire_shape(polyline, inner_polylines_list);
69
+ polyline->shape = shape;
70
+ this->shapes_.push_back(shape);
71
+
72
+ if (treemap.size() > 0)
73
+ { auto treemap_entry = treemap[polyline_index];
74
+ shapes_map[polyline_index] = shape;
75
+ if (treemap_entry.first != -1 && treemap_entry.second != -1) {
76
+ auto it = shapes_map.find(treemap_entry.first);
77
+ if (it != shapes_map.end()) {
78
+ Shape* parent = it->second;
79
+ shape->set_parent_shape(parent);
80
+ shape->fixed = true;
81
+ shape->parent_inner_polyline = parent->inner_polylines[treemap_entry.second];
84
82
  }
85
83
  }
86
84
  }
@@ -106,6 +106,8 @@
106
106
  #include "PolygonFinder/src/polygon/finder/concurrent/PartPool.cpp"
107
107
  #include "PolygonFinder/src/polygon/finder/concurrent/Merger.h"
108
108
  #include "PolygonFinder/src/polygon/finder/concurrent/Merger.cpp"
109
+ #include "PolygonFinder/src/polygon/finder/concurrent/MergerValidator.h"
110
+ #include "PolygonFinder/src/polygon/finder/concurrent/MergerValidator.cpp"
109
111
  #include "PolygonFinder/src/polygon/finder/concurrent/HorizontalMerger.h"
110
112
  #include "PolygonFinder/src/polygon/finder/concurrent/HorizontalMerger.cpp"
111
113
  #include "PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.h"
@@ -13,18 +13,21 @@ module Contrek
13
13
  @current_x = 0
14
14
  @tiles = Queue.new
15
15
  @whole_tile = nil
16
- @previous_boundary = nil
17
16
  @user_options = options
18
17
  if (warn_options = @user_options.keys & IGNORE_OPTIONS).any?
19
18
  warn "[Contrek WARNING] The given options '#{warn_options.join(",")}' will be ignored."
20
19
  end
21
20
  @options = {unsafe_mode: false}.merge(@user_options).except(*IGNORE_OPTIONS)
22
- unless safe?
21
+ if safe?
22
+ @validator = MergerValidator.new(self)
23
+ else
23
24
  warn "[Contrek WARNING] Processing tile with 'unsafe_mode: true'. Incompatible result options might lead to unexpected vector geometry."
24
25
  end
25
26
  end
26
27
 
27
28
  def add_tile(result)
29
+ @validator&.validate_metadata(result)
30
+
28
31
  @height ||= result.metadata[:height]
29
32
  raise ArgumentError, "All results must have the same height" if @height != result.metadata[:height] && safe?
30
33
  @options[:versus] ||= result.metadata[:versus]
@@ -35,8 +38,8 @@ module Contrek
35
38
  end
36
39
  end
37
40
 
38
- validate(result) if safe?
39
41
  end_x = @current_x + result.metadata[:width]
42
+ @validator&.validate(result, @current_x, end_x)
40
43
 
41
44
  tile = Tile.new(
42
45
  finder: self,
@@ -47,9 +50,6 @@ module Contrek
47
50
  tile.assign_raw_polygons!(result[:polygons])
48
51
 
49
52
  @tiles << tile
50
-
51
- @previous_boundary = boundary_coordinates(result.polygons, end_x) if safe?
52
-
53
53
  @maximum_width = end_x
54
54
  @current_x = end_x - 1
55
55
  end
@@ -65,25 +65,6 @@ module Contrek
65
65
 
66
66
  private
67
67
 
68
- def validate(result)
69
- return unless @previous_boundary
70
-
71
- current = boundary_coordinates(result.polygons, @current_x)
72
- unless @previous_boundary == current
73
- raise ArgumentError, "Tile boundary mismatch: adjacent tiles have different edge coordinates"
74
- end
75
- end
76
-
77
- def boundary_coordinates(polygons, boundary_x)
78
- coordinates = []
79
- polygons.each do |polygon|
80
- polygon[:outer].each do |point|
81
- coordinates << point[:y] if point[:x] == boundary_x
82
- end
83
- end
84
- coordinates.sort!
85
- end
86
-
87
68
  def translate(result, offset)
88
69
  result.polygons.each do |polygon|
89
70
  polygon[:outer].each { |p| p[:x] += offset }
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Contrek
4
+ module Concurrent
5
+ class MergerValidator
6
+ def initialize(merger)
7
+ @merger = merger
8
+ end
9
+
10
+ def validate(result, start_x, end_x)
11
+ validate_bounds(result.polygons)
12
+ validate_polygon_order(result.polygons)
13
+ validate_boundary(result, start_x)
14
+
15
+ @previous_boundary = boundary_coordinates(result.polygons, end_x)
16
+ end
17
+
18
+ def validate_metadata(result)
19
+ metadata = result.metadata
20
+ [:width, :height, :versus].each do |key|
21
+ raise ArgumentError, "Missing result metadata: #{key}" unless metadata.key?(key)
22
+ end
23
+ [:width, :height].each do |key|
24
+ value = metadata[key]
25
+ unless value.is_a?(Integer) && value.positive?
26
+ raise ArgumentError, "Invalid result metadata: #{key} must be a positive integer"
27
+ end
28
+ end
29
+ unless [:a, :o].include?(metadata[:versus])
30
+ raise ArgumentError, "Invalid result metadata: unsupported versus option"
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def validate_polygon_order(polygons)
37
+ previous = nil
38
+ polygons.each do |polygon|
39
+ bounds = polygon[:bounds]
40
+ current = if @merger.transpose?
41
+ [bounds[:min_x], bounds[:min_y]]
42
+ else
43
+ [bounds[:min_y], bounds[:min_x]]
44
+ end
45
+ if previous && (current <=> previous) < 0
46
+ raise ArgumentError, "Invalid polygon order: polygons are not in raster scan order"
47
+ end
48
+ previous = current
49
+ end
50
+ end
51
+
52
+ def validate_boundary(result, start_x)
53
+ return unless @previous_boundary
54
+
55
+ current = boundary_coordinates(result.polygons, start_x)
56
+ unless @previous_boundary == current
57
+ raise ArgumentError, "Tile boundary mismatch: adjacent tiles have different edge coordinates"
58
+ end
59
+ end
60
+
61
+ def boundary_coordinates(polygons, boundary_x)
62
+ coordinates = []
63
+ polygons.each do |polygon|
64
+ polygon[:outer].each do |point|
65
+ coordinates << point[:y] if point[:x] == boundary_x
66
+ end
67
+ end
68
+ coordinates.sort!
69
+ end
70
+
71
+ def validate_bounds(polygons)
72
+ polygons.each do |polygon|
73
+ outer = polygon[:outer]
74
+ raise ArgumentError, "Invalid polygon: empty outer contour" if outer.empty?
75
+ bounds = polygon[:bounds]
76
+ min_x = max_x = outer[0][:x]
77
+ min_y = max_y = outer[0][:y]
78
+ outer.each do |point|
79
+ x = point[:x]
80
+ y = point[:y]
81
+ min_x = x if x < min_x
82
+ max_x = x if x > max_x
83
+ min_y = y if y < min_y
84
+ max_y = y if y > max_y
85
+ end
86
+ unless bounds[:min_x] == min_x &&
87
+ bounds[:max_x] == max_x &&
88
+ bounds[:min_y] == min_y &&
89
+ bounds[:max_y] == max_y
90
+ raise ArgumentError, "Invalid polygon bounds: bounding box does not match outer contour"
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -92,7 +92,6 @@ module Contrek
92
92
  @shapes = []
93
93
  shapes_map = {}
94
94
  raw_polylines.each_with_index do |raw_polyline, polyline_index|
95
- next if raw_polyline[:bounds][:max_x] - raw_polyline[:bounds][:min_x] == 0
96
95
  shape = Shape.new.tap do |shape|
97
96
  shape.outer_polyline = Polyline.new(tile: self, polygon: raw_polyline[:outer], shape: shape, bounds: raw_polyline[:bounds])
98
97
  shape.inner_polylines = raw_polyline[:inner].map { |raw| InnerPolyline.new(shape: shape, raw_coordinates: raw) }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Contrek
4
- VERSION = "1.4.5"
4
+ VERSION = "1.4.6"
5
5
  end
data/lib/contrek.rb CHANGED
@@ -45,6 +45,7 @@ require "contrek/finder/concurrent/polyline"
45
45
  require "contrek/finder/concurrent/cluster"
46
46
  require "contrek/finder/concurrent/finder"
47
47
  require "contrek/finder/concurrent/merger"
48
+ require "contrek/finder/concurrent/merger_validator"
48
49
  require "contrek/finder/concurrent/horizontal_merger"
49
50
  require "contrek/finder/concurrent/vertical_merger"
50
51
  require "contrek/finder/concurrent/streaming_merger"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contrek
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.5
4
+ version: 1.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emanuele Cesaroni
@@ -215,6 +215,8 @@ files:
215
215
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/InnerPolyline.h
216
216
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Merger.cpp
217
217
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Merger.h
218
+ - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/MergerValidator.cpp
219
+ - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/MergerValidator.h
218
220
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.cpp
219
221
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.h
220
222
  - ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/PartPool.cpp
@@ -305,6 +307,7 @@ files:
305
307
  - lib/contrek/finder/concurrent/inner_polyline.rb
306
308
  - lib/contrek/finder/concurrent/listable.rb
307
309
  - lib/contrek/finder/concurrent/merger.rb
310
+ - lib/contrek/finder/concurrent/merger_validator.rb
308
311
  - lib/contrek/finder/concurrent/part.rb
309
312
  - lib/contrek/finder/concurrent/partitionable.rb
310
313
  - lib/contrek/finder/concurrent/polyline.rb