contrek 1.0.6 → 1.0.8
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 +4 -4
- data/CHANGELOG.md +11 -1
- data/Gemfile.lock +1 -1
- data/README.md +102 -6
- data/ext/cpp_polygon_finder/PolygonFinder/Makefile +4 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +5 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/FastPngBitmap.cpp +3 -5
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.cpp +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.cpp +2 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.h +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.cpp +28 -8
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.h +1 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.cpp +12 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Hub.cpp +5 -5
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Hub.h +11 -7
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.h +2 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.cpp +108 -66
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.h +5 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +33 -28
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +5 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Position.cpp +2 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Queueable.h +15 -20
- data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +128 -131
- data/lib/contrek/bitmaps/rgb_color.rb +0 -15
- data/lib/contrek/bitmaps/rgb_cpp_color.rb +10 -0
- data/lib/contrek/finder/concurrent/cluster.rb +2 -2
- data/lib/contrek/finder/concurrent/cursor.rb +32 -15
- data/lib/contrek/finder/concurrent/finder.rb +23 -9
- data/lib/contrek/finder/concurrent/hub.rb +2 -2
- data/lib/contrek/finder/concurrent/part.rb +6 -1
- data/lib/contrek/finder/concurrent/partitionable.rb +61 -33
- data/lib/contrek/finder/concurrent/polyline.rb +44 -2
- data/lib/contrek/finder/concurrent/queueable.rb +12 -20
- data/lib/contrek/finder/polygon_finder.rb +8 -6
- data/lib/contrek/finder/result.rb +13 -0
- data/lib/contrek/results/cpp_result.rb +21 -0
- data/lib/contrek/version.rb +1 -1
- data/lib/contrek.rb +6 -3
- metadata +5 -2
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
#include <iostream>
|
|
10
10
|
#include <list>
|
|
11
|
-
#include <rice/rice.hpp>
|
|
12
|
-
#include <rice/stl.hpp>
|
|
13
11
|
#include <vector>
|
|
14
12
|
#include <map>
|
|
15
13
|
#include <string>
|
|
14
|
+
#include <rice/rice.hpp>
|
|
15
|
+
#include <rice/stl.hpp>
|
|
16
16
|
|
|
17
17
|
#include "PolygonFinder/src/polygon/finder/PolygonFinder.h"
|
|
18
18
|
#include "PolygonFinder/src/polygon/finder/PolygonFinder.cpp"
|
|
@@ -86,142 +86,133 @@ extern "C" {
|
|
|
86
86
|
#include "PolygonFinder/src/polygon/bitmaps/spng.h"
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{ public:
|
|
95
|
-
VALUE convert(const std::vector<Point*>& x)
|
|
96
|
-
{ Rice::Array arr;
|
|
97
|
-
for (Point* p : x)
|
|
98
|
-
arr.push(p);
|
|
99
|
-
return arr;
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
template<>
|
|
104
|
-
class To_Ruby<std::list<std::vector<Point*>>>
|
|
105
|
-
{ public:
|
|
106
|
-
VALUE convert(const std::list<std::vector<Point*>>& x)
|
|
107
|
-
{ Rice::Array arr;
|
|
108
|
-
for (const std::vector<Point*>& vec : x)
|
|
109
|
-
{ arr.push(vec);
|
|
110
|
-
}
|
|
111
|
-
return arr;
|
|
112
|
-
}
|
|
113
|
-
};
|
|
89
|
+
class RubyResult {
|
|
90
|
+
public:
|
|
91
|
+
Rice::Array polygons;
|
|
92
|
+
Rice::Hash metadata;
|
|
93
|
+
};
|
|
114
94
|
|
|
115
|
-
|
|
116
|
-
class To_Ruby<Point*>
|
|
117
|
-
{ public:
|
|
118
|
-
VALUE convert(Point* const & x)
|
|
119
|
-
{ Rice::Hash h = Rice::Hash();
|
|
120
|
-
h[Symbol("x")] = x->x;
|
|
121
|
-
h[Symbol("y")] = x->y;
|
|
122
|
-
return(h);
|
|
123
|
-
}
|
|
124
|
-
};
|
|
95
|
+
using namespace Rice;
|
|
125
96
|
|
|
126
|
-
|
|
127
|
-
class To_Ruby<std::map<std::string, double>*>
|
|
128
|
-
{ public:
|
|
129
|
-
VALUE convert(std::map<std::string, double>* const & x)
|
|
130
|
-
{ Rice::Hash return_me = Rice::Hash();
|
|
131
|
-
std::map<std::string, double>::iterator it;
|
|
132
|
-
for ( it = x->begin(); it != x->end(); it++ )
|
|
133
|
-
{ return_me[String(it->first)] = it->second;
|
|
134
|
-
}
|
|
135
|
-
return return_me;
|
|
136
|
-
}
|
|
137
|
-
};
|
|
97
|
+
namespace Rice::detail {
|
|
138
98
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
99
|
+
template<>
|
|
100
|
+
class From_Ruby<std::vector<std::string>*>
|
|
101
|
+
{ public:
|
|
102
|
+
Convertible is_convertible(VALUE value)
|
|
103
|
+
{ switch (rb_type(value))
|
|
104
|
+
{ case RUBY_T_HASH:
|
|
105
|
+
return Convertible::Cast;
|
|
106
|
+
break;
|
|
107
|
+
default:
|
|
108
|
+
return Convertible::None;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
std::vector<std::string>* convert(VALUE value)
|
|
112
|
+
{ std::vector<std::string> *arguments = new std::vector<std::string>();
|
|
113
|
+
if (rb_type(value) == RUBY_T_NIL) return(arguments);
|
|
114
|
+
Rice::Hash hash = (Rice::Hash) value;
|
|
115
|
+
for (Rice::Hash::iterator it = hash.begin(); it != hash.end(); ++it) {
|
|
116
|
+
Rice::String keyString = it->key.to_s();
|
|
117
|
+
Rice::Object value = it->value;
|
|
118
|
+
switch (value.rb_type()) {
|
|
119
|
+
case T_STRING:
|
|
120
|
+
arguments->push_back("--" + keyString.str()+"="+((Rice::String) value).str());
|
|
146
121
|
break;
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
122
|
+
case T_SYMBOL:
|
|
123
|
+
arguments->push_back("--" + keyString.str()+"="+((Rice::Symbol) value).str());
|
|
124
|
+
break;
|
|
125
|
+
case T_FLOAT:
|
|
126
|
+
arguments->push_back("--" + keyString.str()+"="+std::to_string(NUM2DBL(value.value())));
|
|
127
|
+
break;
|
|
128
|
+
case T_FIXNUM:
|
|
129
|
+
arguments->push_back("--" + keyString.str()+"="+std::to_string(NUM2INT(value.value())));
|
|
130
|
+
break;
|
|
131
|
+
case T_TRUE:
|
|
132
|
+
arguments->push_back("--" + keyString.str()+"=true");
|
|
133
|
+
break;
|
|
134
|
+
case T_FALSE:
|
|
135
|
+
arguments->push_back("--" + keyString.str()+"=false");
|
|
136
|
+
break;
|
|
137
|
+
case T_HASH:
|
|
138
|
+
std::vector<std::string>* iv = From_Ruby<std::vector<std::string>*>::convert(value);
|
|
139
|
+
for (std::vector<std::string>::iterator it_iv = iv->begin() ; it_iv != iv->end(); ++it_iv)
|
|
140
|
+
{ (*it_iv).replace(0, 2, "_");
|
|
141
|
+
arguments->push_back("--" + keyString.str() + *it_iv);
|
|
142
|
+
}
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
150
145
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
break;
|
|
162
|
-
case T_SYMBOL:
|
|
163
|
-
arguments->push_back("--" + keyString.str()+"="+((Rice::Symbol) value).str());
|
|
164
|
-
break;
|
|
165
|
-
case T_FLOAT:
|
|
166
|
-
arguments->push_back("--" + keyString.str()+"="+std::to_string(NUM2DBL(value.value())));
|
|
167
|
-
break;
|
|
168
|
-
case T_FIXNUM:
|
|
169
|
-
arguments->push_back("--" + keyString.str()+"="+std::to_string(NUM2INT(value.value())));
|
|
170
|
-
break;
|
|
171
|
-
case T_TRUE:
|
|
172
|
-
arguments->push_back("--" + keyString.str()+"=true");
|
|
173
|
-
break;
|
|
174
|
-
case T_FALSE:
|
|
175
|
-
arguments->push_back("--" + keyString.str()+"=false");
|
|
176
|
-
break;
|
|
177
|
-
case T_HASH:
|
|
178
|
-
std::vector<std::string>* iv = From_Ruby<std::vector<std::string>*>::convert(value);
|
|
179
|
-
for (std::vector<std::string>::iterator it_iv = iv->begin() ; it_iv != iv->end(); ++it_iv)
|
|
180
|
-
{ (*it_iv).replace(0, 2, "_");
|
|
181
|
-
arguments->push_back("--" + keyString.str() + *it_iv);
|
|
182
|
-
}
|
|
183
|
-
break;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
return arguments;
|
|
146
|
+
return arguments;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
template<>
|
|
151
|
+
class To_Ruby<ProcessResult*>
|
|
152
|
+
{public:
|
|
153
|
+
VALUE convert(ProcessResult* const & pr)
|
|
154
|
+
{ if (!pr) {
|
|
155
|
+
return Qnil;
|
|
187
156
|
}
|
|
188
|
-
|
|
157
|
+
RubyResult* rr = new RubyResult();
|
|
158
|
+
Rice::Data_Object<RubyResult> rb_result(rr);
|
|
189
159
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
160
|
+
Rice::Hash return_me = Rice::Hash();
|
|
161
|
+
Rice::Hash benchmarks_rb;
|
|
162
|
+
for (auto const& [name, value] : pr->benchmarks) {
|
|
163
|
+
benchmarks_rb[Rice::String(name)] = value;
|
|
194
164
|
}
|
|
195
|
-
|
|
165
|
+
return_me[Symbol("benchmarks")] = benchmarks_rb;
|
|
166
|
+
return_me[Symbol("groups")] = pr->groups;
|
|
167
|
+
return_me[Symbol("named_sequence")] = pr->named_sequence;
|
|
196
168
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
Rice::Array out;
|
|
206
|
-
for (Polygon& x : pr->polygons)
|
|
207
|
-
{ Rice::Hash h = Rice::Hash();
|
|
208
|
-
h[Symbol("outer")] = x.outer;
|
|
209
|
-
h[Symbol("inner")] = x.inner;
|
|
210
|
-
out.push(h);
|
|
169
|
+
Rice::Array out;
|
|
170
|
+
for (Polygon& x : pr->polygons)
|
|
171
|
+
{ Rice::Hash poly_hash = Rice::Hash();
|
|
172
|
+
// OUTER: std::vector<Point*>
|
|
173
|
+
Rice::Array outer_flat;
|
|
174
|
+
for (Point* p : x.outer) {
|
|
175
|
+
outer_flat.push(p->x);
|
|
176
|
+
outer_flat.push(p->y);
|
|
211
177
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
178
|
+
poly_hash[Symbol("outer")] = outer_flat;
|
|
179
|
+
// INNER: std::list<std::vector<Point*>>
|
|
180
|
+
Rice::Array inner_collection;
|
|
181
|
+
for (const std::vector<Point*>& sequence : x.inner) {
|
|
182
|
+
Rice::Array sequence_flat;
|
|
183
|
+
for (Point* p : sequence) {
|
|
184
|
+
sequence_flat.push(p->x);
|
|
185
|
+
sequence_flat.push(p->y);
|
|
186
|
+
}
|
|
187
|
+
inner_collection.push(sequence_flat);
|
|
219
188
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
189
|
+
poly_hash[Symbol("inner")] = inner_collection;
|
|
190
|
+
out.push(poly_hash);
|
|
191
|
+
}
|
|
192
|
+
rr->polygons = out;
|
|
193
|
+
|
|
194
|
+
// Treemap
|
|
195
|
+
Rice::Array tmapout;
|
|
196
|
+
for (const auto& tm : pr->treemap) {
|
|
197
|
+
Rice::Array tmentry;
|
|
198
|
+
tmentry.push(tm.first);
|
|
199
|
+
tmentry.push(tm.second);
|
|
200
|
+
tmapout.push(tmentry);
|
|
223
201
|
}
|
|
224
|
-
|
|
202
|
+
return_me[Symbol("treemap")] = tmapout;
|
|
203
|
+
rr->metadata = return_me;
|
|
204
|
+
|
|
205
|
+
// Protects objects 'out' e 'return_me' linking them to the ruby instance preventing GC
|
|
206
|
+
// garbage collector to free them before the instance itself.
|
|
207
|
+
Rice::Object ruby_obj = rb_result;
|
|
208
|
+
ruby_obj.iv_set("@polygons_storage", out);
|
|
209
|
+
ruby_obj.iv_set("@metadata_storage", return_me);
|
|
210
|
+
|
|
211
|
+
delete pr;
|
|
212
|
+
return rb_result.value();
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
225
216
|
} // namespace Rice::detail
|
|
226
217
|
|
|
227
218
|
extern "C"
|
|
@@ -276,17 +267,23 @@ void Init_cpp_polygon_finder() {
|
|
|
276
267
|
|
|
277
268
|
Data_Type<RGBNotMatcher> rb_cRGBNotMatcher =
|
|
278
269
|
define_class<RGBNotMatcher, Matcher>("CPPRGBNotMatcher")
|
|
279
|
-
.define_constructor(Constructor<RGBNotMatcher, int>())
|
|
270
|
+
.define_constructor(Constructor<RGBNotMatcher, unsigned int>())
|
|
280
271
|
.define_method("match", &RGBNotMatcher::match);
|
|
281
272
|
|
|
282
273
|
Data_Type<PolygonFinder> rb_cPolygonFinder =
|
|
283
274
|
define_class<PolygonFinder>("CPPPolygonFinder")
|
|
284
|
-
.define_constructor(Constructor<PolygonFinder, Bitmap*, Matcher*, Bitmap*, std::vector<std::string>*>(), Arg("bitmap"), Arg("matcher"), Arg("test_bitmap") = nullptr, Arg("options") = nullptr)
|
|
275
|
+
.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)
|
|
285
276
|
.define_method("get_shapelines", &PolygonFinder::get_shapelines)
|
|
286
|
-
.define_method("process_info", &PolygonFinder::process_info);
|
|
277
|
+
.define_method("process_info", &PolygonFinder::process_info, Rice::Arg("yield_gvl") = true);
|
|
287
278
|
|
|
288
279
|
Data_Type<Finder> rb_cFinder =
|
|
289
280
|
define_class<Finder>("CPPFinder")
|
|
290
|
-
.define_constructor(Constructor<Finder, int, Bitmap*, Matcher*, std::vector<std::string>*>(), Arg("number_of_threads"), Arg("bitmap"), Arg("matcher"), Arg("options") = nullptr)
|
|
291
|
-
.define_method("process_info", &Finder::process_info);
|
|
281
|
+
.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)
|
|
282
|
+
.define_method("process_info", &Finder::process_info, Rice::Arg("yield_gvl") = true);
|
|
283
|
+
|
|
284
|
+
Data_Type<RubyResult> rb_cResult =
|
|
285
|
+
define_class_under<RubyResult>(rb_cFinder, "Result")
|
|
286
|
+
.define_constructor(Constructor<RubyResult>())
|
|
287
|
+
.define_method("polygons", [](RubyResult& rr) { return rr.polygons; })
|
|
288
|
+
.define_method("metadata", [](RubyResult& rr) { return rr.metadata; });
|
|
292
289
|
}
|
|
@@ -3,23 +3,8 @@ module Contrek
|
|
|
3
3
|
class RgbColor
|
|
4
4
|
attr_reader :raw
|
|
5
5
|
def initialize(r:, g:, b:, a: 255)
|
|
6
|
-
@r = r
|
|
7
|
-
@g = g
|
|
8
|
-
@b = b
|
|
9
|
-
@a = a
|
|
10
6
|
@raw = (r << 24) + (g << 16) + (b << 8) + a
|
|
11
7
|
end
|
|
12
|
-
|
|
13
|
-
def to_rgb_raw
|
|
14
|
-
@raw >> 8
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def self.reverse_raw(raw)
|
|
18
|
-
[:a, :b, :g, :r].each_with_object({}) do |c, h|
|
|
19
|
-
h[c] = raw & 0xFF
|
|
20
|
-
raw >>= 8
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
8
|
end
|
|
24
9
|
end
|
|
25
10
|
end
|
|
@@ -3,10 +3,10 @@ module Contrek
|
|
|
3
3
|
class Cluster
|
|
4
4
|
attr_reader :tiles, :hub
|
|
5
5
|
|
|
6
|
-
def initialize(finder:, height:,
|
|
6
|
+
def initialize(finder:, height:, start_x:, end_x:)
|
|
7
7
|
@finder = finder
|
|
8
8
|
@tiles = []
|
|
9
|
-
@hub = Hub.new(
|
|
9
|
+
@hub = Hub.new(start_x:, end_x:)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def add(tile)
|
|
@@ -54,34 +54,51 @@ module Contrek
|
|
|
54
54
|
missing_shapes << shape
|
|
55
55
|
end
|
|
56
56
|
end
|
|
57
|
+
to_delay = connect_missings(missing_shapes)
|
|
58
|
+
while to_delay.any?
|
|
59
|
+
to_delay = connect_missings(to_delay)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
retme = collect_inner_sequences(outer_seq)
|
|
63
|
+
|
|
64
|
+
@polylines_sequence.each do |polyline|
|
|
65
|
+
polyline.turn_on(Polyline::TRACKED_INNER)
|
|
66
|
+
end
|
|
67
|
+
retme
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def connect_missings(missing_shapes)
|
|
73
|
+
delay_shapes = []
|
|
74
|
+
|
|
57
75
|
@polylines_sequence.each do |polyline|
|
|
58
76
|
missing_shapes.each do |missing_shape|
|
|
59
|
-
|
|
60
|
-
next
|
|
61
|
-
|
|
62
|
-
|
|
77
|
+
missing_outer_polyline = missing_shape.outer_polyline
|
|
78
|
+
next if missing_outer_polyline.on?(Polyline::TRACKED_OUTER) ||
|
|
79
|
+
!polyline.vert_intersect?(missing_outer_polyline)
|
|
80
|
+
|
|
81
|
+
if (intersection = polyline.intersection(missing_outer_polyline)).any?
|
|
82
|
+
inject_sequences_left, inject_sequences_right = polyline.sew!(intersection, missing_outer_polyline)
|
|
83
|
+
if inject_sequences_left.nil?
|
|
84
|
+
delay_shapes << missing_shape
|
|
85
|
+
next
|
|
86
|
+
end
|
|
63
87
|
combine!(inject_sequences_right, inject_sequences_left).each do |sewn_sequence|
|
|
64
88
|
sewn_sequence.uniq!
|
|
65
89
|
@orphan_inners << sewn_sequence if sewn_sequence.size > 1 && sewn_sequence.map { |c| c[:x] }.uniq.size > 1 # segmenti non sono ammessi, solo aree
|
|
66
90
|
end
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
91
|
+
missing_outer_polyline.clear!
|
|
92
|
+
missing_outer_polyline.turn_on(Polyline::TRACKED_OUTER)
|
|
93
|
+
missing_outer_polyline.turn_on(Polyline::TRACKED_INNER)
|
|
70
94
|
@orphan_inners += missing_shape.inner_polylines
|
|
71
95
|
end
|
|
72
96
|
end
|
|
73
97
|
end
|
|
74
98
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
@polylines_sequence.each do |polyline|
|
|
78
|
-
polyline.turn_on(Polyline::TRACKED_INNER)
|
|
79
|
-
end
|
|
80
|
-
retme
|
|
99
|
+
delay_shapes
|
|
81
100
|
end
|
|
82
101
|
|
|
83
|
-
private
|
|
84
|
-
|
|
85
102
|
# rubocop:disable Lint/NonLocalExitFromIterator
|
|
86
103
|
def traverse_outer(act_part, all_parts, polylines, shapes, outer_joined_polyline)
|
|
87
104
|
all_parts << act_part if all_parts.last != act_part
|
|
@@ -74,14 +74,17 @@ module Contrek
|
|
|
74
74
|
end
|
|
75
75
|
end.real
|
|
76
76
|
|
|
77
|
-
{
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
77
|
+
metadata = {
|
|
78
|
+
groups: raw_polygons.size,
|
|
79
|
+
benchmarks: {
|
|
80
|
+
total: ((@initialize_time + compress_time) * 1000).round(3),
|
|
81
|
+
init: (@initialize_time * 1000).round(3),
|
|
82
|
+
outer: (@whole_tile.benchmarks[:outer] * 1000).round(3),
|
|
83
|
+
inner: (@whole_tile.benchmarks[:inner] * 1000).round(3),
|
|
84
|
+
compress: ((compress_time * 1000).round(3) if @options.has_key?(:compress))
|
|
85
|
+
}.compact
|
|
86
|
+
}
|
|
87
|
+
Contrek::Finder::Result.new(raw_polygons, metadata)
|
|
85
88
|
end
|
|
86
89
|
|
|
87
90
|
private
|
|
@@ -95,7 +98,18 @@ module Contrek
|
|
|
95
98
|
return
|
|
96
99
|
end
|
|
97
100
|
if (twin_tile = arriving_tiles.find { |b| (b.start_x == (tile.end_x - 1)) || ((b.end_x - 1) == tile.start_x) })
|
|
98
|
-
|
|
101
|
+
|
|
102
|
+
if twin_tile.start_x == (tile.end_x - 1)
|
|
103
|
+
start_x = tile.start_x
|
|
104
|
+
end_x = twin_tile.end_x
|
|
105
|
+
else
|
|
106
|
+
start_x = twin_tile.start_x
|
|
107
|
+
end_x = tile.end_x
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# puts "start = #{start_x} end = #{end_x}"
|
|
111
|
+
|
|
112
|
+
cluster = Cluster.new(finder: self, height: bitmap.h, start_x:, end_x:)
|
|
99
113
|
if twin_tile.start_x == (tile.end_x - 1)
|
|
100
114
|
cluster.add(tile)
|
|
101
115
|
cluster.add(twin_tile)
|
|
@@ -8,7 +8,7 @@ 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
|
|
11
|
+
attr_accessor :next, :circular_next, :prev, :type, :passes, :inverts, :trasmuted, :delayed
|
|
12
12
|
def initialize(type, polyline)
|
|
13
13
|
@type = type
|
|
14
14
|
@polyline = polyline
|
|
@@ -19,12 +19,17 @@ module Contrek
|
|
|
19
19
|
@touched = false
|
|
20
20
|
@inverts = false
|
|
21
21
|
@trasmuted = false
|
|
22
|
+
@delayed = false
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
def is?(type)
|
|
25
26
|
@type == type
|
|
26
27
|
end
|
|
27
28
|
|
|
29
|
+
def set_polyline(polyline)
|
|
30
|
+
@polyline = polyline
|
|
31
|
+
end
|
|
32
|
+
|
|
28
33
|
def add_position(position)
|
|
29
34
|
add(Position.new(position: position, hub: polyline.tile.cluster.hub))
|
|
30
35
|
end
|
|
@@ -16,6 +16,15 @@ module Contrek
|
|
|
16
16
|
new_part.prev = last
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
def insert_after(part, new_part)
|
|
20
|
+
part_index = @parts.index(part)
|
|
21
|
+
@parts.insert(part_index + 1, new_part)
|
|
22
|
+
new_part.prev = part
|
|
23
|
+
new_part.next = new_part.circular_next = part.next
|
|
24
|
+
part.next.prev = new_part if part.next
|
|
25
|
+
part.next = part.circular_next = new_part
|
|
26
|
+
end
|
|
27
|
+
|
|
19
28
|
def find_first_part_by_position(position)
|
|
20
29
|
@parts.find do |part|
|
|
21
30
|
part.is?(Part::SEAM) &&
|
|
@@ -57,48 +66,67 @@ module Contrek
|
|
|
57
66
|
end
|
|
58
67
|
|
|
59
68
|
def sew!(intersection, other)
|
|
60
|
-
matching_part_indexes =
|
|
61
|
-
|
|
62
|
-
next if part.trasmuted
|
|
63
|
-
matching_part_indexes << index if part.intersection_with_array?(intersection)
|
|
64
|
-
end
|
|
65
|
-
other_matching_part_indexes = []
|
|
66
|
-
other.parts.each_with_index do |part, index|
|
|
67
|
-
next if part.trasmuted
|
|
68
|
-
other_matching_part_indexes << index if part.intersection_with_array?(intersection)
|
|
69
|
-
end
|
|
70
|
-
# other_matching_part_indexes and matching_part_indexes always contain at least one element
|
|
69
|
+
matching_part_indexes, other_matching_part_indexes = intersection.transpose.map(&:sort)
|
|
70
|
+
# other_matching_part_indexes and matching_part_indexes always must contain at least one element
|
|
71
71
|
before_parts = other.parts[other_matching_part_indexes.last + 1..]
|
|
72
72
|
after_parts = other_matching_part_indexes.first.zero? ? [] : other.parts[0..other_matching_part_indexes.first - 1]
|
|
73
73
|
part_start = parts[matching_part_indexes.first]
|
|
74
74
|
part_end = parts[matching_part_indexes.last]
|
|
75
75
|
|
|
76
|
-
#
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
76
|
+
# left and right side reduces will be combined and later converted into orphan inners sequences
|
|
77
|
+
returning_data = [[matching_part_indexes, parts], [other_matching_part_indexes, other.parts]].map do |matching_part_indexes, parts|
|
|
78
|
+
lastn = 0
|
|
79
|
+
result = []
|
|
80
|
+
(matching_part_indexes.first + 1).upto(matching_part_indexes.last - 1) do |n|
|
|
81
|
+
if matching_part_indexes.index(n).nil?
|
|
82
|
+
part = parts[n]
|
|
83
|
+
if part.is?(Part::SEAM) && part.size > 0 && !part.delayed # fallback, delays the shape
|
|
84
|
+
part.delayed = true
|
|
85
|
+
return nil
|
|
86
|
+
end
|
|
87
|
+
if (lastn == (n - 1)) && result.any?
|
|
88
|
+
result.last.concat part.to_a
|
|
89
|
+
else
|
|
90
|
+
result << part.to_a
|
|
91
|
+
end
|
|
92
|
+
lastn = n
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
result
|
|
96
|
+
end
|
|
86
97
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
98
|
+
if part_start != part_end
|
|
99
|
+
(matching_part_indexes.last - 1).downto(matching_part_indexes.first + 1) do |n|
|
|
100
|
+
delete_part = parts[n]
|
|
101
|
+
delete_part.prev.next = delete_part.next if delete_part.prev
|
|
102
|
+
delete_part.next.prev = delete_part.prev if delete_part.next
|
|
103
|
+
parts.delete_at(n)
|
|
104
|
+
end
|
|
90
105
|
end
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
106
|
+
|
|
107
|
+
all_parts = before_parts + after_parts
|
|
108
|
+
will_be_last = all_parts.last
|
|
109
|
+
all_parts.reverse_each do |part|
|
|
110
|
+
insert_after(part_start, part)
|
|
111
|
+
other.parts.delete(part)
|
|
112
|
+
part.set_polyline(self)
|
|
96
113
|
end
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
114
|
+
|
|
115
|
+
part_start.type = Part::EXCLUSIVE
|
|
116
|
+
new_end_part = Part.new(Part::EXCLUSIVE, self)
|
|
117
|
+
new_end_part.add(part_end.tail)
|
|
118
|
+
part_start.singleton! # reduce part to its head only
|
|
119
|
+
|
|
120
|
+
if part_start != part_end
|
|
121
|
+
part_end.prev.next = part_end.next if part_end.prev
|
|
122
|
+
part_end.next.prev = part_end.prev if part_end.next
|
|
123
|
+
parts.delete(part_end)
|
|
100
124
|
end
|
|
101
|
-
|
|
125
|
+
insert_after(will_be_last, new_end_part)
|
|
126
|
+
|
|
127
|
+
reset_tracked_endpoints!
|
|
128
|
+
|
|
129
|
+
returning_data
|
|
102
130
|
end
|
|
103
131
|
|
|
104
132
|
private
|