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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +1 -1
- data/README.md +5 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/ContrekApi.h +13 -17
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +78 -33
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/FinderUtils.cpp +31 -101
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/FinderUtils.h +2 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.cpp +1 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/OptionValue.h +91 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Options.h +123 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.cpp +4 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +14 -6
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ClippedPolygonFinder.cpp +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/ClippedPolygonFinder.h +2 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.cpp +19 -11
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.h +5 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/GeoJsonStreamingMerger.h +4 -5
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/HorizontalMerger.cpp +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/HorizontalMerger.h +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Merger.cpp +28 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Merger.h +3 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.cpp +12 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Shape.h +2 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.cpp +16 -6
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/StreamingMerger.h +2 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/SvgStreamingMerger.h +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.cpp +1 -13
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.cpp +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/VerticalMerger.h +1 -1
- data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +66 -24
- data/lib/contrek/finder/concurrent/finder.rb +2 -2
- data/lib/contrek/finder/concurrent/geo_json_streaming_merger.rb +3 -3
- data/lib/contrek/finder/concurrent/merger.rb +17 -1
- data/lib/contrek/finder/concurrent/shape.rb +6 -0
- data/lib/contrek/finder/concurrent/streaming_merger.rb +8 -4
- data/lib/contrek/finder/concurrent/tile.rb +2 -7
- data/lib/contrek/finder/node_cluster.rb +1 -1
- data/lib/contrek/finder/polygon_finder.rb +2 -0
- data/lib/contrek/reducers/visvalingam_reducer.rb +2 -1
- data/lib/contrek/version.rb +1 -1
- metadata +4 -3
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/optionparser.h +0 -2858
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6e79871127e3d6aff04c8bd1e6ea9765d47542249a188b0cf151ce8a005ea29a
|
|
4
|
+
data.tar.gz: '055817b3638fcf582584e45e0ffef001305961321f8a05beb5998399b0be7bc6'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e3007307485a1ce6902f4f95b452b3ef2622fd2c59a0a27d8ee2564e0d8b512bdf8acc15ad5fac30b472b8d14263800324ac19ad74932eb220366860ad7ec60b
|
|
7
|
+
data.tar.gz: 38289075bb92eb56229f1206ff595a0ea65d6bcbbf271dcdc035d60ef8b1c7609cbae687367803ff3d2cb39eae9f8fe670fb893afdcff87df77d8c0ce7b1c928
|
data/CHANGELOG.md
CHANGED
|
@@ -138,3 +138,9 @@ All notable changes to this project will be documented in this file.
|
|
|
138
138
|
|
|
139
139
|
## [1.3.4] - 2026-07-19
|
|
140
140
|
- Refactored core topology from a top-left point model to a 4-vertex pixel-cell model, natively eliminating diagonal ambiguities and rewriting part of the stripe-merging algorithm to ensure perfect geometric stitching on shared nodes. Removed Strict Bounds mode. Added a Douglas-Peucker and a custom raster-compression algorithm that shifts top/right pixel boundaries by 1px to ensure flawless surface rendering as bitmap image.
|
|
141
|
+
|
|
142
|
+
## [1.3.6] - 2026-07-26
|
|
143
|
+
- Removed optionparser.h and the legacy options argument mechanism, replacing them with the new OptionValue.h and Options.h
|
|
144
|
+
- Added polygon compression to the progressive streaming pipeline (StreamingMerger).
|
|
145
|
+
- Added strict validation in progressive streaming. Results passed to add_tile() are now validated to ensure they contain compatible settings (such as versus conventions and compression options).
|
|
146
|
+
- Added unsafe_mode flag to streaming mergers. This allows bypassing compatibility checks when using custom or arbitrary input data.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -128,7 +128,7 @@ rgb_matcher = CPPRGBNotMatcher.new(png_bitmap.rgb_value_at(0, 0))
|
|
|
128
128
|
polygonfinder = CPPPolygonFinder.new(png_bitmap,
|
|
129
129
|
rgb_matcher,
|
|
130
130
|
nil,
|
|
131
|
-
{versus: :a, compress: {visvalingam:
|
|
131
|
+
{versus: :a, compress: {visvalingam: true, visvalingam_tolerance: 1.5}})
|
|
132
132
|
result = polygonfinder.process_info
|
|
133
133
|
# draws the polygons found
|
|
134
134
|
Contrek::Bitmaps::Painting.direct_draw_polygons(result.points, png_image)
|
|
@@ -312,8 +312,11 @@ result.metadata
|
|
|
312
312
|
"total"=>0.05208},
|
|
313
313
|
:groups=>1,
|
|
314
314
|
:named_sequence=>"AFEDCBA",
|
|
315
|
-
:treemap=>[]
|
|
315
|
+
:treemap=>[],
|
|
316
|
+
:options=>{versus: :a, compress: {visvalingam: true, visvalingam_tolerance: 1.5}}
|
|
317
|
+
}
|
|
316
318
|
```
|
|
319
|
+
The options are the original options passed by user.
|
|
317
320
|
|
|
318
321
|
## Treemap
|
|
319
322
|
|
|
@@ -8,17 +8,16 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
#pragma once
|
|
11
|
-
|
|
12
11
|
#include <string>
|
|
13
12
|
#include <vector>
|
|
14
13
|
#include <memory>
|
|
15
14
|
#include <cstdint>
|
|
16
15
|
#include <string_view>
|
|
17
|
-
|
|
18
16
|
#include "Finder.h"
|
|
19
17
|
#include "FastPngBitmap.h"
|
|
20
18
|
#include "RGBNotMatcher.h"
|
|
21
19
|
#include "RGBMatcher.h"
|
|
20
|
+
#include "Options.h"
|
|
22
21
|
|
|
23
22
|
namespace Contrek {
|
|
24
23
|
|
|
@@ -49,7 +48,7 @@ struct Config {
|
|
|
49
48
|
struct TraceContext {
|
|
50
49
|
std::unique_ptr<FastPngBitmap> bitmap;
|
|
51
50
|
std::unique_ptr<Matcher> matcher;
|
|
52
|
-
|
|
51
|
+
Options internal_args;
|
|
53
52
|
std::unique_ptr<Finder> finder;
|
|
54
53
|
std::unique_ptr<ProcessResult> result;
|
|
55
54
|
|
|
@@ -82,23 +81,20 @@ inline TraceContext trace(const std::string& image_path, const Config& cfg = Con
|
|
|
82
81
|
ctx.matcher = std::make_unique<RGBMatcher>(color_to_match);
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
ctx.internal_args = {
|
|
86
|
-
|
|
87
|
-
struct Mapping { bool flag; std::string_view arg; };
|
|
88
|
-
const Mapping mappings[] = {
|
|
89
|
-
{cfg.compress_unique, "--compress_uniq"},
|
|
90
|
-
{cfg.compress_linear, "--compress_linear"},
|
|
91
|
-
{cfg.compress_visvalingam, "--compress_visvalingam"},
|
|
92
|
-
{cfg.treemap, "--treemap"}
|
|
84
|
+
ctx.internal_args = {
|
|
85
|
+
{"versus", Identifier{"a"}},
|
|
93
86
|
};
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
87
|
+
Options compression_opts;
|
|
88
|
+
|
|
89
|
+
if (cfg.compress_unique) compression_opts["uniq"] = true;
|
|
90
|
+
if (cfg.compress_linear) compression_opts["linear"] = true;
|
|
91
|
+
if (cfg.compress_visvalingam) compression_opts["visvalingam"] = true;
|
|
92
|
+
if (cfg.compress_unique || cfg.compress_linear || cfg.compress_visvalingam) ctx.internal_args["compression"] = compression_opts;
|
|
93
|
+
ctx.internal_args["number_of_tiles"] = cfg.tiles;
|
|
98
94
|
if (cfg.connectivity_mode == Connectivity::OMNIDIRECTIONAL) {
|
|
99
|
-
ctx.internal_args
|
|
95
|
+
ctx.internal_args["connectivity"] = 8;
|
|
100
96
|
}
|
|
101
|
-
ctx.finder = std::make_unique<Finder>(cfg.threads, ctx.bitmap.get(), ctx.matcher.get(),
|
|
97
|
+
ctx.finder = std::make_unique<Finder>(cfg.threads, ctx.bitmap.get(), ctx.matcher.get(), ctx.internal_args);
|
|
102
98
|
ctx.result = std::unique_ptr<ProcessResult>(ctx.finder->process_info());
|
|
103
99
|
|
|
104
100
|
return ctx;
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
#include "polygon/matchers/RGBMatcher.h"
|
|
33
33
|
#include "polygon/matchers/RGBNotMatcher.h"
|
|
34
34
|
#include "polygon/matchers/ValueNotMatcher.h"
|
|
35
|
-
#include "polygon/finder/
|
|
35
|
+
#include "polygon/finder/Options.h"
|
|
36
36
|
#include "polygon/finder/concurrent/Finder.h"
|
|
37
37
|
#include "polygon/finder/concurrent/HorizontalMerger.h"
|
|
38
38
|
#include "polygon/finder/concurrent/VerticalMerger.h"
|
|
@@ -53,14 +53,22 @@ void Tests::test_a()
|
|
|
53
53
|
"000000DDDDDD0000"\
|
|
54
54
|
"0000000000000000";
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
Options options = {
|
|
57
|
+
{"versus", Identifier{"a"}},
|
|
58
|
+
{"compress", Options{
|
|
59
|
+
{"uniq", true},
|
|
60
|
+
{"linear", true},
|
|
61
|
+
}},
|
|
62
|
+
{"treemap", true}
|
|
63
|
+
};
|
|
64
|
+
|
|
57
65
|
ValueNotMatcher matcher('0');
|
|
58
66
|
Bitmap b(chunk, 16);
|
|
59
|
-
PolygonFinder pl(&b, &matcher, nullptr,
|
|
67
|
+
PolygonFinder pl(&b, &matcher, nullptr, options);
|
|
60
68
|
ProcessResult *o = pl.process_info();
|
|
61
69
|
// o->print_polygons();
|
|
62
|
-
std::vector<int> outer_array{11, 1,
|
|
63
|
-
std::vector<int> inner_array{
|
|
70
|
+
std::vector<int> outer_array{11, 1, 11, 2, 6, 2, 6, 6, 12, 6, 12, 1 };
|
|
71
|
+
std::vector<int> inner_array{8, 3, 10, 3, 10, 5, 8, 5, 8, 4};
|
|
64
72
|
std::vector<int> array_compare;
|
|
65
73
|
|
|
66
74
|
for (const auto& x : o->polygons)
|
|
@@ -90,10 +98,19 @@ void Tests::test_b()
|
|
|
90
98
|
" XX XX "\
|
|
91
99
|
" XXXXXXXXXXX ";
|
|
92
100
|
|
|
93
|
-
|
|
101
|
+
Options options = {
|
|
102
|
+
{"versus", Identifier{"o"}},
|
|
103
|
+
{"number_of_tiles",2},
|
|
104
|
+
{"compress", Options{
|
|
105
|
+
{"uniq", true},
|
|
106
|
+
{"linear", true},
|
|
107
|
+
}},
|
|
108
|
+
{"treemap", true}
|
|
109
|
+
};
|
|
110
|
+
|
|
94
111
|
ValueNotMatcher matcher(' ');
|
|
95
112
|
Bitmap b(chunk, 16);
|
|
96
|
-
Finder concurrentFinder(2, &b, &matcher,
|
|
113
|
+
Finder concurrentFinder(2, &b, &matcher, options);
|
|
97
114
|
ProcessResult *pro = concurrentFinder.process_info();
|
|
98
115
|
pro->print_polygons();
|
|
99
116
|
delete pro;
|
|
@@ -152,14 +169,21 @@ void Tests::test_d()
|
|
|
152
169
|
FastPngBitmap png_bitmap("../images/sample_10240x10240.png");
|
|
153
170
|
// FastPngBitmap png_bitmap("images/labyrinth.png");
|
|
154
171
|
std::cout << "image_w=" << png_bitmap.w() << " image_h=" << png_bitmap.h() << std::endl;
|
|
155
|
-
std::cout << "image reading time
|
|
172
|
+
std::cout << "image reading time=" << cpu_timer.stop() << std::endl;
|
|
156
173
|
|
|
157
174
|
int color = png_bitmap.value_at(0, 0);
|
|
158
|
-
std::cout << "color =" << color << std::endl;
|
|
175
|
+
std::cout << "color = " << color << std::endl;
|
|
159
176
|
RGBNotMatcher not_matcher(color);
|
|
160
177
|
|
|
161
|
-
|
|
162
|
-
|
|
178
|
+
Options options = {
|
|
179
|
+
{"versus", Identifier{"a"}},
|
|
180
|
+
{"compress", Options{
|
|
181
|
+
{"uniq", true},
|
|
182
|
+
}},
|
|
183
|
+
{"treemap", true}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
PolygonFinder pl(&png_bitmap, ¬_matcher, nullptr, options);
|
|
163
187
|
ProcessResult *o = pl.process_info();
|
|
164
188
|
o->print_info();
|
|
165
189
|
delete o;
|
|
@@ -176,8 +200,14 @@ void Tests::test_e()
|
|
|
176
200
|
std::cout << "color = " << color << std::endl;
|
|
177
201
|
RGBNotMatcher not_matcher(color);
|
|
178
202
|
|
|
179
|
-
|
|
180
|
-
|
|
203
|
+
Options options = {
|
|
204
|
+
{"versus", Identifier{"a"}},
|
|
205
|
+
{"number_of_tiles",2},
|
|
206
|
+
{"compress", Options{
|
|
207
|
+
{"uniq", true},
|
|
208
|
+
}},
|
|
209
|
+
};
|
|
210
|
+
Finder pl(2, &png_bitmap, ¬_matcher, options);
|
|
181
211
|
ProcessResult *o = pl.process_info();
|
|
182
212
|
o->print_info();
|
|
183
213
|
std::cout << "polygons = " << o->groups << std::endl;
|
|
@@ -211,8 +241,14 @@ void Tests::test_g()
|
|
|
211
241
|
std::cout << "color = " << color << std::endl;
|
|
212
242
|
RGBNotMatcher not_matcher(color);
|
|
213
243
|
|
|
214
|
-
|
|
215
|
-
|
|
244
|
+
Options options = {
|
|
245
|
+
{"versus", Identifier{"a"}},
|
|
246
|
+
{"number_of_tiles",2},
|
|
247
|
+
{"compress", Options{
|
|
248
|
+
{"uniq", true},
|
|
249
|
+
}},
|
|
250
|
+
};
|
|
251
|
+
Finder pl(2, &raw_bitmap, ¬_matcher, options);
|
|
216
252
|
ProcessResult *o = pl.process_info();
|
|
217
253
|
// o->print_info();
|
|
218
254
|
// o->print_polygons();
|
|
@@ -231,10 +267,15 @@ void Tests::test_h()
|
|
|
231
267
|
"00 " \
|
|
232
268
|
"0000000000" \
|
|
233
269
|
"0000000000";
|
|
234
|
-
|
|
270
|
+
Options options = {
|
|
271
|
+
{"versus", Identifier{"a"}},
|
|
272
|
+
{"compress", Options{
|
|
273
|
+
{"uniq", true},
|
|
274
|
+
}},
|
|
275
|
+
};
|
|
235
276
|
ValueNotMatcher matcher(' ');
|
|
236
277
|
Bitmap b_left(left, 10);
|
|
237
|
-
PolygonFinder pl_left(&b_left, &matcher, nullptr,
|
|
278
|
+
PolygonFinder pl_left(&b_left, &matcher, nullptr, options);
|
|
238
279
|
ProcessResult *left_result = pl_left.process_info();
|
|
239
280
|
|
|
240
281
|
std::string right =
|
|
@@ -248,11 +289,11 @@ void Tests::test_h()
|
|
|
248
289
|
"0000000000" \
|
|
249
290
|
"0000000000";
|
|
250
291
|
Bitmap b_right(right, 10);
|
|
251
|
-
PolygonFinder pl_right(&b_right, &matcher, nullptr,
|
|
292
|
+
PolygonFinder pl_right(&b_right, &matcher, nullptr, options);
|
|
252
293
|
ProcessResult *right_result = pl_right.process_info();
|
|
253
294
|
|
|
254
|
-
|
|
255
|
-
HorizontalMerger hmerger(1,
|
|
295
|
+
Options merger_options = {};
|
|
296
|
+
HorizontalMerger hmerger(1, merger_options);
|
|
256
297
|
hmerger.add_tile(*left_result);
|
|
257
298
|
hmerger.add_tile(*right_result);
|
|
258
299
|
ProcessResult *merged_result = hmerger.process_info();
|
|
@@ -282,8 +323,8 @@ double get_peak_rss() {
|
|
|
282
323
|
*/
|
|
283
324
|
void stream_png_image(const std::string& filepath, uint32_t stripe_height, bool generate_svg = false, bool generate_png = false) {
|
|
284
325
|
std::vector<ProcessResult*> result_clones;
|
|
285
|
-
|
|
286
|
-
VerticalMerger vmerger(0,
|
|
326
|
+
Options options = {};
|
|
327
|
+
VerticalMerger vmerger(0, options);
|
|
287
328
|
|
|
288
329
|
// opens image to stream
|
|
289
330
|
FILE* fp = fopen(filepath.c_str(), "rb");
|
|
@@ -340,10 +381,10 @@ void stream_png_image(const std::string& filepath, uint32_t stripe_height, bool
|
|
|
340
381
|
if (ret != 0 && ret != SPNG_EOI) break;
|
|
341
382
|
}
|
|
342
383
|
// stripe contour tracing
|
|
343
|
-
|
|
344
|
-
"
|
|
384
|
+
Options options = {
|
|
385
|
+
{"versus", Identifier{"a"}},
|
|
345
386
|
};
|
|
346
|
-
PolygonFinder polygon_finder(&stripe_bitmap, ¬_matcher, nullptr,
|
|
387
|
+
PolygonFinder polygon_finder(&stripe_bitmap, ¬_matcher, nullptr, options);
|
|
347
388
|
ProcessResult *result = polygon_finder.process_info();
|
|
348
389
|
if (result) {
|
|
349
390
|
std::cout << "stripe " << stripe_count << ": found polygons " << result->groups << std::endl;
|
|
@@ -400,7 +441,9 @@ double get_current_rss_mb() {
|
|
|
400
441
|
|
|
401
442
|
void stream_progressive_png_image(const std::string& filepath, uint32_t stripe_height) {
|
|
402
443
|
std::vector<ProcessResult*> result_clones;
|
|
403
|
-
|
|
444
|
+
Options voptions = {
|
|
445
|
+
{"bounds", true},
|
|
446
|
+
};
|
|
404
447
|
// opens image to stream
|
|
405
448
|
FILE* fp = fopen(filepath.c_str(), "rb");
|
|
406
449
|
if (!fp) {
|
|
@@ -439,7 +482,7 @@ void stream_progressive_png_image(const std::string& filepath, uint32_t stripe_h
|
|
|
439
482
|
std::vector<char> buffer(4 * 1024 * 1024); // Buffer (4MB)
|
|
440
483
|
shared_stream.rdbuf()->pubsetbuf(buffer.data(), buffer.size());
|
|
441
484
|
|
|
442
|
-
SvgStreamingMerger vmerger(0,
|
|
485
|
+
SvgStreamingMerger vmerger(0, voptions, &shared_stream, total_width, total_height);
|
|
443
486
|
// GeoJsonStreamingMerger vmerger(0, &varguments, &shared_stream, 4294901760);
|
|
444
487
|
try {
|
|
445
488
|
size_t row_size = static_cast<size_t>(total_width) * 4;
|
|
@@ -466,14 +509,16 @@ void stream_progressive_png_image(const std::string& filepath, uint32_t stripe_h
|
|
|
466
509
|
if (ret != 0 && ret != SPNG_EOI) break;
|
|
467
510
|
}
|
|
468
511
|
// stripe contour tracing
|
|
469
|
-
|
|
470
|
-
"
|
|
471
|
-
"
|
|
472
|
-
"
|
|
473
|
-
|
|
512
|
+
Options options = {
|
|
513
|
+
{"versus", Identifier{"a"}},
|
|
514
|
+
{"bounds", true},
|
|
515
|
+
{"compress", Options{
|
|
516
|
+
{"uniq", true},
|
|
517
|
+
{"linear", true},
|
|
518
|
+
}},
|
|
474
519
|
};
|
|
475
520
|
|
|
476
|
-
PolygonFinder polygon_finder(&stripe_bitmap, ¬_matcher, nullptr,
|
|
521
|
+
PolygonFinder polygon_finder(&stripe_bitmap, ¬_matcher, nullptr, options);
|
|
477
522
|
ProcessResult *result = polygon_finder.process_info();
|
|
478
523
|
if (result) {
|
|
479
524
|
std::cout << "stripe " << stripe_count << ": found polygons " << result->groups << std::endl;
|
|
@@ -9,118 +9,48 @@
|
|
|
9
9
|
|
|
10
10
|
#include <iostream>
|
|
11
11
|
#include <string>
|
|
12
|
-
#include <
|
|
12
|
+
#include <algorithm>
|
|
13
13
|
#include "PolygonFinder.h"
|
|
14
14
|
#include "FinderUtils.h"
|
|
15
|
-
#include "optionparser.h"
|
|
16
15
|
|
|
17
|
-
void FinderUtils::sanitize_options(pf_Options& options,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
void FinderUtils::sanitize_options(pf_Options& options, const Options& incoming_options) {
|
|
17
|
+
const Identifier versus = incoming_options.get<Identifier>("versus", options.versus == Node::A ? "a" : "o");
|
|
18
|
+
options.versus = versus == "a" ? Node::A : Node::O;
|
|
19
|
+
options.number_of_tiles = std::max(1, static_cast<int>(incoming_options.get<std::int64_t>(
|
|
20
|
+
"number_of_tiles",
|
|
21
|
+
options.number_of_tiles)));
|
|
22
|
+
options.connectivity_offset = incoming_options.get<std::int64_t>(
|
|
23
|
+
"connectivity",
|
|
24
|
+
options.connectivity_offset == 1 ? 8 : 4) == 8;
|
|
25
|
+
options.treemap = incoming_options.get<bool>("treemap", options.treemap);
|
|
26
|
+
options.named_sequences = incoming_options.get<bool>(
|
|
27
|
+
"named_sequences",
|
|
28
|
+
options.named_sequences);
|
|
29
|
+
options.bounds = incoming_options.get<bool>("bounds", options.bounds);
|
|
30
|
+
options.unsafe_mode = incoming_options.get<bool>("unsafe_mode", options.unsafe_mode);
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
{NUMBER_OF_TILES, 0, "", "number_of_tiles", option::Arg::Optional, 0},
|
|
37
|
-
{TREEMAP, 0, "", "treemap", option::Arg::None, 0},
|
|
38
|
-
{NAMED_SEQUENCES, 0, "", "named_sequences", option::Arg::None, 0},
|
|
39
|
-
{BOUNDS, 0, "", "bounds", option::Arg::None, 0},
|
|
40
|
-
{VERSUS, 0, "v", "versus", option::Arg::Optional, 0},
|
|
41
|
-
{CONNECTIVITY, 0, "c", "connectivity", option::Arg::Optional, 0},
|
|
42
|
-
{0, 0, 0, 0, 0, 0}
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
option::Stats stats(usage, argc, argv);
|
|
46
|
-
option::Option ioptions[stats.options_max], buffer[stats.buffer_max];
|
|
47
|
-
option::Parser parse(usage, argc, argv, ioptions, buffer);
|
|
48
|
-
|
|
49
|
-
if (parse.error()) return;
|
|
50
|
-
// VERSUS
|
|
51
|
-
if (ioptions[VERSUS].count() > 0)
|
|
52
|
-
{ for (option::Option* opt = ioptions[VERSUS]; opt; opt = opt->next())
|
|
53
|
-
{ std::string opts = opt->arg;
|
|
54
|
-
options.versus = (opts.compare("a") == 0 ? Node::A : Node::O);
|
|
55
|
-
break;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
// COMPRESS UNIQ
|
|
59
|
-
if (ioptions[COMPRESS_UNIQ].count() > 0)
|
|
60
|
-
{ options.compress_uniq = true;
|
|
61
|
-
}
|
|
62
|
-
// NUMBER_OF_TILES
|
|
63
|
-
if (ioptions[NUMBER_OF_TILES].count() > 0)
|
|
64
|
-
{ try {
|
|
65
|
-
options.number_of_tiles = std::stoi(ioptions[NUMBER_OF_TILES].arg);
|
|
66
|
-
if (options.number_of_tiles <= 0) options.number_of_tiles = 1;
|
|
32
|
+
if (const Options* compress = incoming_options.get_options("compress")) {
|
|
33
|
+
options.compress_uniq = compress->get<bool>("uniq", options.compress_uniq);
|
|
34
|
+
options.compress_linear = compress->get<bool>("linear", options.compress_linear);
|
|
35
|
+
options.compress_raster = compress->get<bool>("raster", options.compress_raster);
|
|
36
|
+
options.compress_douglas_peucker = compress->get<bool>("douglas_peucker", options.compress_douglas_peucker);
|
|
37
|
+
options.compress_visvalingam = compress->get<bool>("visvalingam", options.compress_visvalingam);
|
|
38
|
+
if (compress->contains("visvalingam_tolerance")) {
|
|
39
|
+
options.compress_visvalingam = true;
|
|
40
|
+
options.compress_visvalingam_tolerance = static_cast<float>(compress->get<double>(
|
|
41
|
+
"visvalingam_tolerance",
|
|
42
|
+
options.compress_visvalingam_tolerance));
|
|
67
43
|
}
|
|
68
|
-
catch (const std::invalid_argument&) {
|
|
69
|
-
std::cerr << "Errore: --number_of_tiles requires a number\n";
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
// CONNECTIVITY
|
|
73
|
-
if (ioptions[CONNECTIVITY].count() > 0)
|
|
74
|
-
{ try {
|
|
75
|
-
if (std::stoi(ioptions[CONNECTIVITY].arg) == 8) options.connectivity_offset = 1;
|
|
76
|
-
}
|
|
77
|
-
catch (const std::invalid_argument&) {
|
|
78
|
-
std::cerr << "Errore: --connectivity requires a number\n";
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
// TREEMAP
|
|
82
|
-
if (ioptions[TREEMAP].count() > 0)
|
|
83
|
-
{ options.treemap = true;
|
|
84
44
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
{ options.named_sequences = true;
|
|
88
|
-
}
|
|
89
|
-
// BOUNDS
|
|
90
|
-
if (ioptions[BOUNDS].count() > 0)
|
|
91
|
-
{ options.bounds = true;
|
|
92
|
-
}
|
|
93
|
-
// COMPRESS LINEAR
|
|
94
|
-
if (ioptions[COMPRESS_LINEAR].count() > 0)
|
|
95
|
-
{ options.compress_linear = true;
|
|
96
|
-
}
|
|
97
|
-
// COMPRESS UNIQ
|
|
98
|
-
if (ioptions[COMPRESS_VISVALINGAM].count() > 0)
|
|
99
|
-
{ options.compress_visvalingam = true;
|
|
100
|
-
}
|
|
101
|
-
if (ioptions[COMPRESS_VISVALINGAM_TOLERANCE].count() > 0)
|
|
102
|
-
{ options.compress_visvalingam = true;
|
|
103
|
-
for (option::Option* opt = ioptions[COMPRESS_VISVALINGAM_TOLERANCE]; opt; opt = opt->next())
|
|
104
|
-
{ std::string opts = opt->arg;
|
|
105
|
-
options.compress_visvalingam_tolerance = strtof(opt->arg, 0);
|
|
106
|
-
break;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
// COMPRESS RASTER
|
|
110
|
-
if (ioptions[COMPRESS_RASTER].count() > 0)
|
|
111
|
-
{ options.compress_raster = true;
|
|
112
|
-
}
|
|
113
|
-
// COMPRESS DOUGLAS PEUCKER
|
|
114
|
-
if (ioptions[COMPRESS_DOUGLAS_PEUCKER].count() > 0)
|
|
115
|
-
{ options.compress_douglas_peucker = true;
|
|
116
|
-
}
|
|
117
|
-
/* std::cout << "-----------" << std::endl;
|
|
45
|
+
|
|
46
|
+
/*std::cout << "-----------" << std::endl;
|
|
118
47
|
std::cout << "versus " << options.versus << std::endl;
|
|
119
48
|
std::cout << "bounds " << options.bounds << std::endl;
|
|
120
49
|
std::cout << "number_of_tiles " << options.number_of_tiles << std::endl;
|
|
121
50
|
std::cout << "uniq " << options.compress_uniq << std::endl;
|
|
122
51
|
std::cout << "linear " << options.compress_linear << std::endl;
|
|
52
|
+
std::cout << "treemap " << options.treemap << std::endl;
|
|
123
53
|
std::cout << "visvalingam " << options.compress_visvalingam << std::endl;
|
|
124
|
-
std::cout << "visvalingam
|
|
54
|
+
std::cout << "visvalingam tolerance " << options.compress_visvalingam_tolerance << std::endl;
|
|
125
55
|
std::cout << "-----------" << std::endl; */
|
|
126
56
|
}
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
#pragma once
|
|
11
11
|
#include <string>
|
|
12
12
|
#include <vector>
|
|
13
|
+
#include "Options.h"
|
|
13
14
|
|
|
14
15
|
class FinderUtils {
|
|
15
16
|
public:
|
|
16
|
-
static void sanitize_options(pf_Options& options,
|
|
17
|
+
static void sanitize_options(pf_Options& options, const Options& incoming_options);
|
|
17
18
|
};
|
|
@@ -43,8 +43,7 @@ NodeCluster::~NodeCluster() {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
void NodeCluster::compress_coords(std::list<Polygon>& polygons, pf_Options options) {
|
|
46
|
-
if (!(options.
|
|
47
|
-
options.compress_douglas_peucker || options.compress_visvalingam)) return;
|
|
46
|
+
if (!(options.any_compression())) return;
|
|
48
47
|
|
|
49
48
|
auto compress_sequence = [&](std::vector<Point>& points_vec) {
|
|
50
49
|
if (points_vec.empty()) return;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* OptionValue.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
|
+
#pragma once
|
|
11
|
+
#include <cstdint>
|
|
12
|
+
#include <memory>
|
|
13
|
+
#include <string>
|
|
14
|
+
#include <utility>
|
|
15
|
+
#include <variant>
|
|
16
|
+
|
|
17
|
+
class Options;
|
|
18
|
+
|
|
19
|
+
struct Identifier {
|
|
20
|
+
std::string value;
|
|
21
|
+
Identifier() = default;
|
|
22
|
+
Identifier(const char* v) : value(v) {}
|
|
23
|
+
Identifier(std::string v) : value(std::move(v)) {}
|
|
24
|
+
bool operator==(const Identifier& other) const {
|
|
25
|
+
return value == other.value;
|
|
26
|
+
}
|
|
27
|
+
bool operator!=(const Identifier& other) const {
|
|
28
|
+
return value != other.value;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
class OptionValue {
|
|
33
|
+
public:
|
|
34
|
+
using NestedOptions = std::shared_ptr<Options>;
|
|
35
|
+
|
|
36
|
+
using Value = std::variant<
|
|
37
|
+
std::monostate,
|
|
38
|
+
bool,
|
|
39
|
+
std::int64_t,
|
|
40
|
+
double,
|
|
41
|
+
std::string,
|
|
42
|
+
Identifier,
|
|
43
|
+
NestedOptions>;
|
|
44
|
+
|
|
45
|
+
OptionValue() = default;
|
|
46
|
+
OptionValue(bool value) : value_(value) {}
|
|
47
|
+
OptionValue(int value) : value_(static_cast<std::int64_t>(value)) {}
|
|
48
|
+
OptionValue(std::int64_t value) : value_(value) {}
|
|
49
|
+
OptionValue(double value) : value_(value) {}
|
|
50
|
+
OptionValue(const char* value) : value_(std::string(value)) {}
|
|
51
|
+
OptionValue(std::string value) : value_(std::move(value)) {}
|
|
52
|
+
OptionValue(Identifier value) : value_(std::move(value)) {}
|
|
53
|
+
OptionValue(const Options& value);
|
|
54
|
+
OptionValue(Options&& value);
|
|
55
|
+
bool is_bool() const { return std::holds_alternative<bool>(value_); }
|
|
56
|
+
bool is_integer() const { return std::holds_alternative<std::int64_t>(value_); }
|
|
57
|
+
bool is_double() const {return std::holds_alternative<double>(value_);}
|
|
58
|
+
bool is_string() const { return std::holds_alternative<std::string>(value_); }
|
|
59
|
+
bool is_options() const { return std::holds_alternative<NestedOptions>(value_); }
|
|
60
|
+
bool is_identifier() const { return std::holds_alternative<Identifier>(value_); }
|
|
61
|
+
bool as_bool() const { return std::get<bool>(value_); }
|
|
62
|
+
std::int64_t as_integer() const { return std::get<std::int64_t>(value_); }
|
|
63
|
+
double as_double() const { return std::get<double>(value_); }
|
|
64
|
+
const std::string& as_string() const { return std::get<std::string>(value_); }
|
|
65
|
+
std::string& as_string() { return std::get<std::string>(value_); }
|
|
66
|
+
const Options& as_options() const;
|
|
67
|
+
Options& as_options();
|
|
68
|
+
const Identifier& as_identifier() const { return std::get<Identifier>(value_); }
|
|
69
|
+
Identifier& as_identifier() { return std::get<Identifier>(value_);}
|
|
70
|
+
|
|
71
|
+
template <typename T>
|
|
72
|
+
bool is() const { return std::holds_alternative<T>(value_); }
|
|
73
|
+
|
|
74
|
+
template <typename T>
|
|
75
|
+
const T& as() const { return std::get<T>(value_); }
|
|
76
|
+
|
|
77
|
+
template <typename T>
|
|
78
|
+
T& as() { return std::get<T>(value_);}
|
|
79
|
+
|
|
80
|
+
template <typename T>
|
|
81
|
+
const T* get_if() const { return std::get_if<T>(&value_); }
|
|
82
|
+
|
|
83
|
+
template <typename T>
|
|
84
|
+
T* get_if() {return std::get_if<T>(&value_); }
|
|
85
|
+
|
|
86
|
+
const Value& value() const { return value_; }
|
|
87
|
+
Value& value() {return value_;}
|
|
88
|
+
|
|
89
|
+
private:
|
|
90
|
+
Value value_;
|
|
91
|
+
};
|