contrek 1.2.5 → 1.2.7
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 +10 -0
- data/Gemfile.lock +1 -1
- data/README.md +12 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +20 -12
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/RawBitmap.cpp +4 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/RawBitmap.h +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/bitmaps/spng.c +17 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/FinderUtils.cpp +4 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.cpp +1 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +17 -29
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.cpp +4 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.h +2 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Merger.cpp +2 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.cpp +7 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Polyline.h +1 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.cpp +4 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.cpp +1 -1
- data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +9 -6
- data/lib/contrek/cpp/cpp_result.rb +3 -2
- data/lib/contrek/finder/concurrent/tile.rb +3 -2
- data/lib/contrek/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ae46fa52ddce3383ef534142814ed28ddc5cae45042e677c8f445140bee67e82
|
|
4
|
+
data.tar.gz: 57cbaf53a0d6e8c7d31bdfcef0718c94654ceaf0fd7b2be84325751dc29f6224
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ee922b6b787ac0f91b98a2e7d608c351499ea5405e325a0eb6d23f751a29075b390c08d757824132c7fbef7d64cef9f3af7dbb11709506e84777ff652f9f15fc
|
|
7
|
+
data.tar.gz: 848102a6980857b1f4d3914e60de04408d0f7a4cc4c950a20b3fa8ef7231e31db029220eb6e3fb71847b6986a09c0d7b1fedae70f8e30e8ef758a3adeabeddcd
|
data/CHANGELOG.md
CHANGED
|
@@ -106,3 +106,13 @@ All notable changes to this project will be documented in this file.
|
|
|
106
106
|
## [1.2.5] - 2026-05-27
|
|
107
107
|
### Changed
|
|
108
108
|
- **Refactored `ProcessResult.clone()`:** Switched from fragmented dynamic allocation to a contiguous `std::vector` with explicit `.reserve()`. Eliminates heap fragmentation during high-res streaming.
|
|
109
|
+
|
|
110
|
+
## [1.2.6] - 2026-05-31
|
|
111
|
+
### Changed
|
|
112
|
+
- **Refactored `spng.c` function `rgb8_row_to_rgba8`:** Extended a loop counter to `size_t` (previously limited to `uint32_t`), which was causing segmentation faults when reading massive images (e.g., 81920x81920).
|
|
113
|
+
- **Refactored `RawBitmap.define` function:** Updated area and size calculations to use full 64-bit integers.
|
|
114
|
+
- **Refactored `PolygonFinder.to_svg_stream()` function:** Optimized performance to efficiently handle massive SVG streams of 2 GB and beyond.
|
|
115
|
+
|
|
116
|
+
## [1.2.7] - 2026-06-02
|
|
117
|
+
### Changed
|
|
118
|
+
- **Refactored `bounds` option:** Starting from this release, precalculated bounds for each polygon can now be requested in concurrent mode as well, in addition to single-threaded mode.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -286,6 +286,18 @@ result.points
|
|
|
286
286
|
For pure Ruby implementations (`{ native: false }`), coordinates are always expressed as points.
|
|
287
287
|
In this case, both `polygons` and `points` return the same data, represented as hashes with `x` and `y` keys.
|
|
288
288
|
|
|
289
|
+
For each returned polygon, it is possible to get its bounding box. You just need to request it as an option (`bounds`), for example:
|
|
290
|
+
```ruby
|
|
291
|
+
{named_sequences: true, bounds: true, compress: {uniq: true, linear: true}}
|
|
292
|
+
```
|
|
293
|
+
Each entry will contain the precalculated bounds key:
|
|
294
|
+
```ruby
|
|
295
|
+
[{:bounds=>{:min_x=>3, :max_x=>11, :min_y=>1, :max_y=>3},
|
|
296
|
+
:outer=>[{:x=>3, :y=>1}, {:x=>3, :y=>3}, {:x=>11, :y=>3}, {:x=>11, :y=>1}],
|
|
297
|
+
:inner=>[]}]
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
|
|
289
301
|
## Metadata
|
|
290
302
|
|
|
291
303
|
Metadata associated with the result can be accessed via:
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
#include "Tests.h"
|
|
11
|
+
#include <sys/resource.h>
|
|
11
12
|
#include <string.h>
|
|
12
13
|
#include <iostream>
|
|
13
14
|
#include <list>
|
|
@@ -17,7 +18,6 @@
|
|
|
17
18
|
#include <cstring>
|
|
18
19
|
#include <algorithm>
|
|
19
20
|
#include <cstdio>
|
|
20
|
-
#include <sys/resource.h>
|
|
21
21
|
|
|
22
22
|
#include "polygon/finder/PolygonFinder.h"
|
|
23
23
|
#include "polygon/finder/concurrent/ClippedPolygonFinder.h"
|
|
@@ -279,7 +279,7 @@ double get_peak_rss() {
|
|
|
279
279
|
This approach allows for processing large PNG files on systems where memory
|
|
280
280
|
would otherwise be insufficient.
|
|
281
281
|
*/
|
|
282
|
-
void stream_png_image(const std::string& filepath, uint32_t stripe_height) {
|
|
282
|
+
void stream_png_image(const std::string& filepath, uint32_t stripe_height, bool generate_svg = false, bool generate_png = false) {
|
|
283
283
|
std::vector<ProcessResult*> result_clones;
|
|
284
284
|
std::vector<std::string> varguments = {};
|
|
285
285
|
VerticalMerger vmerger(0, &varguments);
|
|
@@ -305,6 +305,7 @@ void stream_png_image(const std::string& filepath, uint32_t stripe_height) {
|
|
|
305
305
|
|
|
306
306
|
// allocates stripe buffer
|
|
307
307
|
RawBitmap stripe_bitmap;
|
|
308
|
+
std::cout << total_width << " " << stripe_height << std::endl;
|
|
308
309
|
stripe_bitmap.define(total_width, stripe_height, 4, true);
|
|
309
310
|
RGBNotMatcher not_matcher(-1);
|
|
310
311
|
|
|
@@ -315,6 +316,7 @@ void stream_png_image(const std::string& filepath, uint32_t stripe_height) {
|
|
|
315
316
|
}
|
|
316
317
|
|
|
317
318
|
size_t row_size = static_cast<size_t>(total_width) * 4;
|
|
319
|
+
int stripe_count = 0;
|
|
318
320
|
// main stripes loop
|
|
319
321
|
for (uint32_t current_y_offset = 0; current_y_offset < total_height; current_y_offset += stripe_height) {
|
|
320
322
|
int uncovered_height = total_height - current_y_offset;
|
|
@@ -344,12 +346,13 @@ void stream_png_image(const std::string& filepath, uint32_t stripe_height) {
|
|
|
344
346
|
PolygonFinder polygon_finder(&stripe_bitmap, ¬_matcher, nullptr, &finder_arguments);
|
|
345
347
|
ProcessResult *result = polygon_finder.process_info();
|
|
346
348
|
if (result) {
|
|
347
|
-
std::cout << "
|
|
349
|
+
std::cout << "stripe " << stripe_count << ": found polygons " << result->groups << std::endl;
|
|
348
350
|
ProcessResult* safe_result = result->clone();
|
|
349
351
|
result_clones.push_back(safe_result);
|
|
350
352
|
vmerger.add_tile(*safe_result);
|
|
351
353
|
delete result;
|
|
352
354
|
}
|
|
355
|
+
stripe_count++;
|
|
353
356
|
}
|
|
354
357
|
|
|
355
358
|
std::cout << "Merging polygons ..." << std::endl;
|
|
@@ -357,15 +360,20 @@ void stream_png_image(const std::string& filepath, uint32_t stripe_height) {
|
|
|
357
360
|
|
|
358
361
|
if (merged_result) {
|
|
359
362
|
std::cout << "Founds total polygons: " << merged_result->groups << std::endl;
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
363
|
+
if (generate_png) {
|
|
364
|
+
RawBitmap full_bitmap;
|
|
365
|
+
full_bitmap.define(total_width, total_height, 4, true);
|
|
366
|
+
full_bitmap.fill(255, 255, 255);
|
|
367
|
+
merged_result->draw_on_bitmap(full_bitmap);
|
|
368
|
+
std::cout << "Saving whole png ..." << std::endl;
|
|
369
|
+
if (full_bitmap.save_to_png("whole.png")) {
|
|
370
|
+
std::cout << "Png saved!" << std::endl;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
if (generate_svg) {
|
|
374
|
+
merged_result->save_svg("whole.svg");
|
|
375
|
+
std::cout << "Svg saved!" << std::endl;
|
|
376
|
+
}
|
|
369
377
|
}
|
|
370
378
|
delete merged_result;
|
|
371
379
|
// frees memory
|
|
@@ -56,16 +56,16 @@ void RawBitmap::draw_pixel(int x, int y, unsigned char r, unsigned char g, unsig
|
|
|
56
56
|
if (bpp > 3) p[3] = a;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
{ this->width
|
|
59
|
+
size_t RawBitmap::define(uint width, uint height, int bytes_per_pixel, bool clear)
|
|
60
|
+
{ this->width = width;
|
|
61
61
|
this->height = height;
|
|
62
62
|
this->bpp = bytes_per_pixel;
|
|
63
|
-
|
|
63
|
+
size_t dimension = static_cast<size_t>(width) * static_cast<size_t>(height) * static_cast<size_t>(bytes_per_pixel);
|
|
64
64
|
this->image = std::make_unique<unsigned char[]>(dimension);
|
|
65
65
|
if (clear) {
|
|
66
66
|
std::fill(image.get(), image.get() + dimension, 0);
|
|
67
67
|
}
|
|
68
|
-
return dimension;
|
|
68
|
+
return static_cast<uint32_t>(dimension);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
void RawBitmap::fill(unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
|
|
@@ -25,7 +25,7 @@ class RawBitmap : public Bitmap {
|
|
|
25
25
|
unsigned int rgb_value_at(int x, int y);
|
|
26
26
|
const unsigned char* get_row_ptr(int y) const;
|
|
27
27
|
int get_bytes_per_pixel() const;
|
|
28
|
-
|
|
28
|
+
size_t define(uint width, uint height, int bytes_per_pixel, bool clear = false);
|
|
29
29
|
void draw_pixel(int x, int y, unsigned char r, unsigned char g, unsigned char b, unsigned char a = 255);
|
|
30
30
|
bool save_to_png(const std::string& filename);
|
|
31
31
|
void fill(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 255);
|
|
@@ -534,7 +534,7 @@ static void u16_row_to_bigendian(void *row, size_t size)
|
|
|
534
534
|
write_u16(&px[i], px[i]);
|
|
535
535
|
}
|
|
536
536
|
}
|
|
537
|
-
|
|
537
|
+
/*
|
|
538
538
|
static void rgb8_row_to_rgba8(const unsigned char *row, unsigned char *out, uint32_t n)
|
|
539
539
|
{
|
|
540
540
|
uint32_t i;
|
|
@@ -543,6 +543,22 @@ static void rgb8_row_to_rgba8(const unsigned char *row, unsigned char *out, uint
|
|
|
543
543
|
memcpy(out + i * 4, row + i * 3, 3);
|
|
544
544
|
out[i*4+3] = 255;
|
|
545
545
|
}
|
|
546
|
+
}*/
|
|
547
|
+
|
|
548
|
+
/* Fix overflow Gigapixel images */
|
|
549
|
+
static void rgb8_row_to_rgba8(const unsigned char *row, unsigned char *out, uint32_t n)
|
|
550
|
+
{
|
|
551
|
+
size_t i;
|
|
552
|
+
for(i=0; i < n; i++)
|
|
553
|
+
{
|
|
554
|
+
out[0] = row[0];
|
|
555
|
+
out[1] = row[1];
|
|
556
|
+
out[2] = row[2];
|
|
557
|
+
out[3] = 255;
|
|
558
|
+
|
|
559
|
+
out += 4;
|
|
560
|
+
row += 3;
|
|
561
|
+
}
|
|
546
562
|
}
|
|
547
563
|
|
|
548
564
|
static unsigned num_channels(const struct spng_ihdr *ihdr)
|
|
@@ -108,12 +108,13 @@ void FinderUtils::sanitize_options(pf_Options& options, std::vector<std::string>
|
|
|
108
108
|
break;
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
-
/*std::cout << "-----------" << std::endl;
|
|
111
|
+
/* std::cout << "-----------" << std::endl;
|
|
112
112
|
std::cout << "versus " << options.versus << std::endl;
|
|
113
|
+
std::cout << "bounds " << options.bounds << std::endl;
|
|
113
114
|
std::cout << "number_of_tiles " << options.number_of_tiles << std::endl;
|
|
114
115
|
std::cout << "uniq " << options.compress_uniq << std::endl;
|
|
115
116
|
std::cout << "linear " << options.compress_linear << std::endl;
|
|
116
117
|
std::cout << "visvalingam " << options.compress_visvalingam << std::endl;
|
|
117
|
-
std::cout << options.compress_visvalingam_tolerance << std::endl;
|
|
118
|
-
std::cout << "-----------" << std::endl
|
|
118
|
+
std::cout << "visvalingam tolernace " << options.compress_visvalingam_tolerance << std::endl;
|
|
119
|
+
std::cout << "-----------" << std::endl; */
|
|
119
120
|
}
|
|
@@ -107,6 +107,7 @@ ProcessResult* PolygonFinder::process_info() {
|
|
|
107
107
|
pr->treemap = this->node_cluster->treemap;
|
|
108
108
|
pr->width = this->source_bitmap->w();
|
|
109
109
|
pr->height = this->source_bitmap->h();
|
|
110
|
+
pr->has_bounds = this->node_cluster->options->bounds;
|
|
110
111
|
|
|
111
112
|
if (this->node_cluster->options->named_sequences && typeid(*this->source_bitmap) == typeid(Bitmap))
|
|
112
113
|
{ std::string sequence;
|
|
@@ -59,6 +59,7 @@ struct pf_Options {
|
|
|
59
59
|
struct ProcessResult {
|
|
60
60
|
int groups;
|
|
61
61
|
int width, height;
|
|
62
|
+
bool has_bounds = false;
|
|
62
63
|
std::map<std::string, double> benchmarks;
|
|
63
64
|
std::list<Polygon> polygons;
|
|
64
65
|
std::string named_sequence;
|
|
@@ -147,50 +148,37 @@ struct ProcessResult {
|
|
|
147
148
|
return new_res;
|
|
148
149
|
}
|
|
149
150
|
|
|
150
|
-
std::
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
"<svg xmlns=\"http://www.w3.org/2000/svg\" "
|
|
154
|
-
"width=\"" + std::to_string(width) +
|
|
155
|
-
"\" height=\"" + std::to_string(height) + "\">");
|
|
151
|
+
void to_svg_stream(std::ostream& os) const {
|
|
152
|
+
os << "<svg xmlns=\"http://www.w3.org/2000/svg\" "
|
|
153
|
+
<< "width=\"" << width << "\" height=\"" << height << "\">\n";
|
|
156
154
|
for (const auto& poly : polygons) {
|
|
157
|
-
|
|
158
|
-
|
|
155
|
+
// --- OUTER (Red) ---
|
|
156
|
+
if (!poly.outer.empty()) {
|
|
157
|
+
os << "<polygon points=\"";
|
|
159
158
|
bool first = true;
|
|
160
159
|
for (const Point* p : poly.outer) {
|
|
161
160
|
if (!p) continue;
|
|
162
|
-
if (!first)
|
|
163
|
-
pts << " ";
|
|
161
|
+
if (!first) os << " ";
|
|
164
162
|
first = false;
|
|
165
|
-
|
|
163
|
+
os << p->x << "," << p->y;
|
|
166
164
|
}
|
|
167
|
-
|
|
168
|
-
"<polygon points=\"" + pts.str() +
|
|
169
|
-
"\" fill=\"none\" stroke=\"red\" stroke-width=\"1\"/>");
|
|
165
|
+
os << "\" fill=\"none\" stroke=\"red\" stroke-width=\"1\"/>\n";
|
|
170
166
|
}
|
|
171
|
-
//
|
|
167
|
+
// --- INNER (Green) ---
|
|
172
168
|
for (const auto& sequence : poly.inner) {
|
|
173
169
|
if (sequence.empty()) continue;
|
|
174
|
-
|
|
170
|
+
os << "<polygon points=\"";
|
|
175
171
|
bool first = true;
|
|
176
172
|
for (const Point* p : sequence) {
|
|
177
173
|
if (!p) continue;
|
|
178
|
-
if (!first)
|
|
174
|
+
if (!first) os << " ";
|
|
179
175
|
first = false;
|
|
180
|
-
|
|
176
|
+
os << p->x << "," << p->y;
|
|
181
177
|
}
|
|
182
|
-
|
|
183
|
-
"<polygon points=\"" + pts.str() +
|
|
184
|
-
"\" fill=\"none\" stroke=\"green\" stroke-width=\"1\"/>");
|
|
178
|
+
os << "\" fill=\"none\" stroke=\"green\" stroke-width=\"1\"/>\n";
|
|
185
179
|
}
|
|
186
180
|
}
|
|
187
|
-
|
|
188
|
-
std::ostringstream result;
|
|
189
|
-
for (size_t i = 0; i < lines.size(); ++i) {
|
|
190
|
-
result << lines[i];
|
|
191
|
-
if (i + 1 < lines.size()) result << "\n";
|
|
192
|
-
}
|
|
193
|
-
return result.str();
|
|
181
|
+
os << "</svg>";
|
|
194
182
|
}
|
|
195
183
|
|
|
196
184
|
void save_svg(const std::string& filename) const {
|
|
@@ -198,7 +186,7 @@ struct ProcessResult {
|
|
|
198
186
|
if (!file.is_open()) {
|
|
199
187
|
throw std::runtime_error("Unable to open SVG file: " + filename);
|
|
200
188
|
}
|
|
201
|
-
file
|
|
189
|
+
to_svg_stream(file);
|
|
202
190
|
file.close();
|
|
203
191
|
}
|
|
204
192
|
};
|
|
@@ -60,7 +60,7 @@ Finder::Finder(int number_of_threads, Bitmap *bitmap, Matcher *matcher, std::vec
|
|
|
60
60
|
Tile* tile = new Tile(this, payload.tile_start_x, payload.tile_end_x,
|
|
61
61
|
std::to_string(payload.tile_index), Benchmarks {0, 0});
|
|
62
62
|
tile->initial_process(finder);
|
|
63
|
-
|
|
63
|
+
tiles_.queue_push(tile);
|
|
64
64
|
});
|
|
65
65
|
|
|
66
66
|
x = tile_end_x - 1;
|
|
@@ -79,7 +79,7 @@ void Finder::process_tiles() {
|
|
|
79
79
|
std::vector<Tile*> arriving_tiles;
|
|
80
80
|
|
|
81
81
|
while (true) {
|
|
82
|
-
Tile* tile =
|
|
82
|
+
Tile* tile = tiles_.queue_pop();
|
|
83
83
|
|
|
84
84
|
if (tile->whole()) {
|
|
85
85
|
this->whole_tile = tile;
|
|
@@ -116,7 +116,7 @@ void Finder::process_tiles() {
|
|
|
116
116
|
arriving_tiles.erase(it);
|
|
117
117
|
enqueue(cluster, [this](Cluster* c) {
|
|
118
118
|
Tile* merged_tile = c->merge_tiles();
|
|
119
|
-
|
|
119
|
+
tiles_.queue_push(merged_tile);
|
|
120
120
|
delete c;
|
|
121
121
|
});
|
|
122
122
|
} else {
|
|
@@ -146,6 +146,7 @@ ProcessResult* Finder::process_info() {
|
|
|
146
146
|
pr->groups = pr->polygons.size();
|
|
147
147
|
pr->width = this->maximum_width_;
|
|
148
148
|
pr->height = this->height;
|
|
149
|
+
pr->has_bounds = this->options_.bounds;
|
|
149
150
|
FakeCluster fake_cluster(pr->polygons, this->options_);
|
|
150
151
|
cpu_timer.start();
|
|
151
152
|
fake_cluster.compress_coords(pr->polygons, this->options_);
|
|
@@ -42,7 +42,7 @@ class Finder : public Poolable {
|
|
|
42
42
|
CpuTimer cpu_timer;
|
|
43
43
|
|
|
44
44
|
protected:
|
|
45
|
-
Queue<Tile*>
|
|
45
|
+
Queue<Tile*> tiles_;
|
|
46
46
|
int maximum_width_;
|
|
47
47
|
int height = 0;
|
|
48
48
|
void process_tiles();
|
|
@@ -55,4 +55,5 @@ class Finder : public Poolable {
|
|
|
55
55
|
int maximum_width() const { return maximum_width_; }
|
|
56
56
|
virtual ProcessResult* process_info();
|
|
57
57
|
const pf_Options& options() const { return options_; }
|
|
58
|
+
Queue<Tile*>& tiles() { return tiles_; }
|
|
58
59
|
};
|
|
@@ -21,9 +21,9 @@ void Merger::add_tile(ProcessResult& result)
|
|
|
21
21
|
this->height = result.height;
|
|
22
22
|
}
|
|
23
23
|
int end_x = this->current_x + result.width;
|
|
24
|
-
Tile* tile = new Tile(this, this->current_x, end_x, std::to_string(
|
|
24
|
+
Tile* tile = new Tile(this, this->current_x, end_x, std::to_string(tiles_.size()), Benchmarks {0, 0});
|
|
25
25
|
tile->assign_raw_polygons(result.polygons, result.treemap);
|
|
26
|
-
|
|
26
|
+
tiles_.queue_push(tile);
|
|
27
27
|
|
|
28
28
|
this->maximum_width_ = end_x;
|
|
29
29
|
this->current_x = end_x - 1;
|
|
@@ -95,3 +95,10 @@ std::string Polyline::named() {
|
|
|
95
95
|
return this->named_;
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
|
+
|
|
99
|
+
void Polyline::fill_bounds(RectBounds& target_bounds) const {
|
|
100
|
+
target_bounds.min_x = this->min_x;
|
|
101
|
+
target_bounds.max_x = this->max_x;
|
|
102
|
+
target_bounds.min_y = this->min_y_;
|
|
103
|
+
target_bounds.max_y = this->max_y_;
|
|
104
|
+
}
|
|
@@ -52,6 +52,7 @@ class Polyline : public Partitionable {
|
|
|
52
52
|
InnerPolyline* inside_inner_polyline = nullptr;
|
|
53
53
|
std::string named();
|
|
54
54
|
void set_named(std::string force_named) { this->named_ = force_named; }
|
|
55
|
+
void fill_bounds(RectBounds& target_bounds) const;
|
|
55
56
|
|
|
56
57
|
private:
|
|
57
58
|
std::vector<Point*> raw_;
|
|
@@ -107,10 +107,14 @@ std::string Tile::toString() {
|
|
|
107
107
|
|
|
108
108
|
std::list<Polygon> Tile::to_raw_polygons()
|
|
109
109
|
{ std::list<Polygon> retme;
|
|
110
|
+
bool bounds = this->finder->options().bounds;
|
|
110
111
|
for (Shape* s : shapes_)
|
|
111
112
|
{ if (s->outer_polyline && !s->outer_polyline->is_empty())
|
|
112
113
|
{ Polygon poly;
|
|
113
114
|
poly.outer = s->outer_polyline->raw();
|
|
115
|
+
if (bounds) {
|
|
116
|
+
s->outer_polyline->fill_bounds(poly.bounds);
|
|
117
|
+
}
|
|
114
118
|
if (!s->inner_polylines.empty()) {
|
|
115
119
|
for (auto inner : s->inner_polylines) {
|
|
116
120
|
poly.inner.push_back(inner->raw());
|
|
@@ -21,7 +21,7 @@ VerticalMerger::VerticalMerger(int number_of_threads, std::vector<std::string> *
|
|
|
21
21
|
|
|
22
22
|
void VerticalMerger::add_tile(ProcessResult& result)
|
|
23
23
|
{ transpose(result);
|
|
24
|
-
if (this->
|
|
24
|
+
if (this->tiles_.size() > 0) {
|
|
25
25
|
translate(result, this->current_x);
|
|
26
26
|
}
|
|
27
27
|
adjust(result);
|
|
@@ -172,6 +172,7 @@ class To_Ruby<ProcessResult*>
|
|
|
172
172
|
}
|
|
173
173
|
RubyResult* rr = new RubyResult();
|
|
174
174
|
Rice::Data_Object<RubyResult> rb_result(rr);
|
|
175
|
+
bool inject_bounds = pr->has_bounds;
|
|
175
176
|
|
|
176
177
|
Rice::Hash return_me = Rice::Hash();
|
|
177
178
|
Rice::Hash benchmarks_rb;
|
|
@@ -206,12 +207,14 @@ class To_Ruby<ProcessResult*>
|
|
|
206
207
|
}
|
|
207
208
|
poly_hash[Symbol("inner")] = inner_collection;
|
|
208
209
|
// BOUNDS
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
210
|
+
if (inject_bounds) {
|
|
211
|
+
Rice::Hash bounds_hash = Rice::Hash();
|
|
212
|
+
bounds_hash[Symbol("min_x")] = x.bounds.min_x;
|
|
213
|
+
bounds_hash[Symbol("max_x")] = x.bounds.max_x;
|
|
214
|
+
bounds_hash[Symbol("min_y")] = x.bounds.min_y;
|
|
215
|
+
bounds_hash[Symbol("max_y")] = x.bounds.max_y;
|
|
216
|
+
poly_hash[Symbol("bounds")] = bounds_hash;
|
|
217
|
+
}
|
|
215
218
|
|
|
216
219
|
out.push(poly_hash);
|
|
217
220
|
}
|
|
@@ -19,8 +19,9 @@ module Contrek
|
|
|
19
19
|
def points
|
|
20
20
|
raw_list = polygons.to_a
|
|
21
21
|
@to_points ||= raw_list.map do |polygon|
|
|
22
|
-
{
|
|
23
|
-
|
|
22
|
+
{bounds: (polygon[:bounds] if polygon.key?(:bounds)),
|
|
23
|
+
outer: self.class.to_points(polygon[:outer]),
|
|
24
|
+
inner: polygon[:inner].map { |s| self.class.to_points(s) }}.compact
|
|
24
25
|
end
|
|
25
26
|
end
|
|
26
27
|
|
|
@@ -54,8 +54,9 @@ module Contrek
|
|
|
54
54
|
def to_raw_polygons
|
|
55
55
|
@shapes.filter_map do |shape|
|
|
56
56
|
unless shape.outer_polyline.empty?
|
|
57
|
-
{
|
|
58
|
-
|
|
57
|
+
{bounds: (shape.outer_polyline.get_bounds if @finder.options[:bounds]),
|
|
58
|
+
outer: shape.outer_polyline.raw,
|
|
59
|
+
inner: shape.inner_polylines.map(&:raw)}.compact
|
|
59
60
|
end
|
|
60
61
|
end
|
|
61
62
|
end
|
data/lib/contrek/version.rb
CHANGED
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.2.
|
|
4
|
+
version: 1.2.7
|
|
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-
|
|
11
|
+
date: 2026-06-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rspec
|