1
1
// Boost.Geometry (aka GGL, Generic Geometry Library)
2
2
// Unit Test
3
3
4
- // Copyright (c) 2010-2017 Barend Gehrels, Amsterdam, the Netherlands.
4
+ // Copyright (c) 2010-2025 Barend Gehrels, Amsterdam, the Netherlands.
5
5
6
6
// This file was modified by Oracle on 2022.
7
7
// Modifications copyright (c) 2022, Oracle and/or its affiliates.
11
11
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12
12
// http://www.boost.org/LICENSE_1_0.txt)
13
13
14
- // #define BOOST_GEOMETRY_DEBUG_ENRICH
15
- // #define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
14
+
15
+ #if defined(TEST_WITH_GEOJSON)
16
+ #define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
17
+ #define BOOST_GEOMETRY_DEBUG_IDENTIFIER
18
+ #endif
16
19
17
20
#include < geometry_test_common.hpp>
18
21
33
36
#include < boost/geometry/strategies/strategies.hpp>
34
37
35
38
#include < boost/geometry/io/wkt/wkt.hpp>
36
- #include < boost/geometry/multi/io/wkt/wkt.hpp>
37
-
38
- #include < boost/geometry/multi/algorithms/for_each.hpp>
39
39
40
- #include < boost/geometry/multi/geometries/multi_linestring.hpp>
41
- #include < boost/geometry/multi/geometries/multi_polygon.hpp>
42
-
43
-
44
- #if defined(TEST_WITH_SVG)
45
- # include < boost/geometry/io/svg/svg_mapper.hpp>
46
- # include < boost/geometry/io/svg/write_svg_multi.hpp>
47
- # include < boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
40
+ #if defined(TEST_WITH_GEOJSON)
41
+ #include < boost/geometry/extensions/gis/io/geojson/geojson_writer.hpp>
42
+ #include " dissolve_geojson_visitor.hpp"
48
43
#endif
49
44
50
45
@@ -176,135 +171,6 @@ namespace
176
171
std::string const dissolve_ticket10713 = " POLYGON((-0.7189743518829346 4.1308121681213379, 0.0831791982054710 4.1034231185913086, 0.1004156470298767 4.1107301712036133, 0.1044322624802589 4.1026973724365234, 0.0831791982054710 4.1034231185913086, -0.7711903452873230 3.7412264347076416, -0.7189743518829346 4.1308121681213379))" ;
177
172
}
178
173
179
-
180
- #if defined(TEST_WITH_SVG)
181
- template <typename Mapper>
182
- struct map_visitor
183
- {
184
- map_visitor (Mapper& mapper)
185
- : m_mapper(mapper)
186
- {}
187
-
188
- template <typename Turns>
189
- void visit_turns (int phase, Turns const & turns)
190
- {
191
- typedef typename boost::range_value<Turns>::type turn_type;
192
- std::size_t index = 0 ;
193
- for (turn_type const & turn : turns)
194
- {
195
- switch (phase)
196
- {
197
- case 2 : // after self_turns and enrich
198
- if (turn.discarded )
199
- {
200
- m_mapper.map (turn.point , " fill:rgb(255,128,0);" , 2 );
201
- }
202
- else
203
- {
204
- m_mapper.map (turn.point , " fill:rgb(255,128,0);"
205
- " stroke:rgb(0,0,0);stroke-width:1" , 4 );
206
- }
207
- break ;
208
- case 3 : // after enrich/traverse
209
- label_turn (index, turn, -2 , " fill:rgb(0,0,128);" );
210
- break ;
211
- }
212
- index++;
213
- }
214
- }
215
-
216
- template <typename Clusters, typename Turns>
217
- void visit_clusters (Clusters const & , Turns const & ) {}
218
-
219
- template <typename Turns, typename Turn, typename Operation>
220
- void visit_traverse (Turns const & , Turn const & , Operation const & , char const *)
221
- {}
222
-
223
- template <typename Turns, typename Turn, typename Operation>
224
- void visit_traverse_reject (Turns const & , Turn const & , Operation const & ,
225
- bg::detail::overlay::traverse_error_type )
226
- {}
227
-
228
- template <typename Rings>
229
- void visit_generated_rings (Rings const & rings)
230
- {
231
- typedef typename boost::range_value<Rings>::type ring_type;
232
- for (ring_type const & ring : rings)
233
- {
234
- double const area = bg::area (ring);
235
- std::string const color = area < 0 ? " rgb(255,0,0)" : " rgb(0,0,255)" ;
236
- std::string const style = " stroke:" + color
237
- + " ;stroke-width:0.1;fill-opacity:0.1;fill:" + color;
238
- m_mapper.map (ring, style);
239
- }
240
- }
241
-
242
-
243
- private :
244
-
245
- template <typename Turn>
246
- bool label_operation (Turn const & turn, std::size_t index, std::ostream& os)
247
- {
248
- os << bg::operation_char (turn.operations [index].operation );
249
- bool result = false ;
250
- if (! turn.discarded )
251
- {
252
- os << " ->" << turn.operations [index].enriched .get_next_turn_index ();
253
- result = true ;
254
- }
255
- if (turn.operations [index].enriched .prefer_start )
256
- {
257
- os << " $" ;
258
- }
259
- if (! turn.operations [index].enriched .startable )
260
- {
261
- os << " @" ;
262
- }
263
-
264
- return result;
265
- }
266
-
267
- template <typename Turn>
268
- void label_turn (std::size_t index, Turn const & turn, int y_offset, std::string const & color)
269
- {
270
- std::ostringstream out;
271
- out << index;
272
- if (turn.cluster_id != -1 )
273
- {
274
- out << " c=" << turn.cluster_id << " " ;
275
- }
276
- bool lab1 = label_operation (turn, 0 , out);
277
- out << " / " ;
278
- bool lab2 = label_operation (turn, 1 , out);
279
- if (turn.discarded )
280
- {
281
- out << " !" ;
282
- }
283
-
284
- std::string font8 = " font-family:Arial;font-size:6px" ;
285
- std::string font6 = " font-family:Arial;font-size:4px" ;
286
- std::string style = color + " ;" + font8;
287
- if (turn.discarded )
288
- {
289
- style = " fill:rgb(92,92,92);" + font6;
290
- }
291
- else if (turn.cluster_id != -1 )
292
- {
293
- style = color + " ;" + font8;
294
- }
295
- else if (! lab1 || ! lab2)
296
- {
297
- style = color + " ;" + font6;
298
- }
299
-
300
- m_mapper.text (turn.point , out.str (), style, 5 , y_offset, 6 );
301
- }
302
-
303
- Mapper& m_mapper;
304
- };
305
-
306
- #endif
307
-
308
174
// ! Unittest settings
309
175
struct ut_settings
310
176
{
@@ -334,6 +200,17 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry,
334
200
std::size_t expected_point_count,
335
201
ut_settings const & settings)
336
202
{
203
+ #if defined(TEST_WITH_GEOJSON)
204
+ std::ostringstream filename;
205
+ // For QGis, it is usually convenient to always write to the same geojson file.
206
+ filename << " /tmp/"
207
+ // << caseid << "_"
208
+ << " dissolve.geojson" ;
209
+ std::ofstream geojson_file (filename.str ().c_str ());
210
+
211
+ boost::geometry::geojson_writer writer (geojson_file);
212
+ #endif
213
+
337
214
using coordinate_type = typename bg::coordinate_type<Geometry>::type;
338
215
339
216
static const bool is_line = bg::geometry_id<GeometryOut>::type::value == 2 ;
@@ -350,59 +227,21 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry,
350
227
Geometry, Geometry
351
228
>::type;
352
229
353
- using rescale_policy_type = typename bg::rescale_policy_type
354
- <
355
- typename bg::point_type<Geometry>::type
356
- >::type;
357
-
358
- rescale_policy_type robust_policy
359
- = bg::get_rescale_policy<rescale_policy_type>(geometry);
360
-
361
- // This will optionally also create SVG with turn-debug information
362
230
strategy_type strategy;
363
231
364
-
365
- #if ! defined(TEST_WITH_SVG)
366
- bg::detail::overlay::overlay_null_visitor visitor;
232
+ #if defined(TEST_WITH_GEOJSON)
233
+ geojson_visitor visitor (writer);
367
234
#else
368
- std::ostringstream filename;
369
- filename << " dissolve_" << caseid << " _"
370
- << string_from_type<coordinate_type>::name ()
371
- << " .svg" ;
372
-
373
- std::ofstream svg (filename.str ().c_str ());
374
-
375
- using mapper_type = bg::svg_mapper
376
- <
377
- typename bg::point_type<Geometry>::type
378
- >;
379
-
380
- mapper_type mapper (svg, 500 , 500 );
381
- mapper.add (geometry);
382
-
383
- mapper.map (geometry, " fill-opacity:0.5;fill:rgb(153,204,0);"
384
- " stroke:rgb(153,204,0);stroke-width:2;fill-rule:nonzero;" );
385
-
386
- map_visitor<mapper_type> visitor (mapper);
387
- #endif
235
+ bg::detail::overlay::overlay_null_visitor visitor;
236
+ #endif
388
237
389
238
bg::dispatch::dissolve
390
239
<
391
240
Geometry,
392
241
GeometryOut,
393
242
false
394
- >::apply (geometry, robust_policy, std::back_inserter (dissolved1),
243
+ >::apply (geometry, std::back_inserter (dissolved1),
395
244
strategy, visitor);
396
-
397
- #if defined(TEST_WITH_SVG)
398
- for (GeometryOut& dissolved : dissolved1)
399
- {
400
- mapper.map (dissolved, " fill-opacity:0.1;fill:rgb(255,0,0);"
401
- " stroke-opacity:0.4;stroke:rgb(255,0,255);stroke-width:3;"
402
- " fill-rule:nonzero;" );
403
- }
404
- #endif
405
-
406
245
}
407
246
408
247
if (settings.test_validity )
@@ -482,8 +321,19 @@ void test_dissolve(std::string const& caseid, Geometry const& geometry,
482
321
BOOST_CHECK_MESSAGE (wkt1 == wkt3, caseid << " : output differs: " << wkt1 << " VERSUS " << wkt3);
483
322
}
484
323
}
485
- }
486
324
325
+ #if defined(TEST_WITH_GEOJSON)
326
+ writer.feature (geometry);
327
+ writer.add_property (" type" , " input" );
328
+
329
+ for (const auto & polygon : dissolved3)
330
+ {
331
+ writer.feature (polygon);
332
+ writer.add_property (" type" , " dissolved" );
333
+ }
334
+ #endif
335
+
336
+ }
487
337
488
338
template <typename Geometry, typename GeometryOut>
489
339
void test_one (std::string caseid, std::string const & wkt,
@@ -505,6 +355,8 @@ void test_one(std::string caseid, std::string const& wkt,
505
355
expected_clip_count, expected_hole_count, expected_point_count,
506
356
settings);
507
357
358
+ #ifdef BOOST_GEOMETRY_TEST_REVERSE
359
+
508
360
// Verify if reversed version is indeed identical (it should, because each
509
361
// ring is now corrected within dissolve itself
510
362
bg::reverse (geometry);
@@ -514,6 +366,7 @@ void test_one(std::string caseid, std::string const& wkt,
514
366
expected_area,
515
367
expected_clip_count, expected_hole_count, expected_point_count,
516
368
settings);
369
+ #endif
517
370
518
371
#ifdef BOOST_GEOMETRY_TEST_MULTI_PERMUTATIONS
519
372
// Test different combinations of a multi-polygon
@@ -652,7 +505,9 @@ void test_all(ut_settings const& settings_for_sensitive_cases)
652
505
653
506
int test_main (int , char * [])
654
507
{
508
+ #if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
655
509
test_all<bg::model::d2::point_xy<float >, true >(ut_settings (0.01 ));
510
+ #endif
656
511
test_all<bg::model::d2::point_xy<double >, true >(ut_settings ());
657
512
// Counter clockwise input does not work correctly in all cases, it is
658
513
// partly a problem of the test itself
0 commit comments