Skip to content

Commit b6eb7ec

Browse files
committed
Impose min number of segments per arc during linearization
This commit sets a fixed minimum of two segments per non-circular arc and three segments per circular arc. Funded by City of Helsinki. Fixes #3719 Closes postgis#320 git-svn-id: http://svn.osgeo.org/postgis/trunk@16998 b70326c6-7e19-0410-871a-916f4a2858ee
1 parent 73f8752 commit b6eb7ec

File tree

9 files changed

+201
-130
lines changed

9 files changed

+201
-130
lines changed

doc/introduction.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@
317317
<listitem><simpara><ulink url="https://www.camptocamp.com">Camptocamp</ulink></simpara></listitem>
318318
<listitem><simpara><ulink url="https://carto.com">Carto</ulink></simpara></listitem>
319319
<listitem><simpara><ulink url="https://www.boston.gov">City of Boston (DND)</ulink></simpara></listitem>
320+
<listitem><simpara><ulink url="https://www.hel.fi">City of Helsinki</ulink></simpara></listitem>
320321
<listitem><simpara><ulink url="https://blog.cleverelephant.ca">Clever Elephant Solutions</ulink></simpara></listitem>
321322
<listitem><simpara><ulink url="https://www.alveo.coop">Cooperativa Alveo</ulink></simpara></listitem>
322323
<listitem><simpara><ulink url="http://www.elecnor-deimos.com">Deimos Space</ulink></simpara></listitem>

doc/reference_processing.xml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@ Supported bits are:
976976

977977
<para>Availability: 1.3.0</para>
978978
<para>Enhanced: 2.4.0 added support for max-deviation and max-angle tolerance, and for symmetric output.</para>
979+
<para>Enhanced: 3.0.0 implemented a minimum number of segments per linearized arc to prevent topological collapse.</para>
979980

980981
<para>&sfs_compliant;</para>
981982
<para>&sqlmm_compliant; SQL-MM 3: 7.1.7</para>
@@ -3027,13 +3028,13 @@ select ST_WrapX(the_geom, -30, 360);
30273028
<refsection>
30283029
<title>Examples</title>
30293030
<para>A circle simplified too much becomes a triangle, medium an octagon, </para>
3030-
<programlisting>SELECT ST_Npoints(the_geom) AS np_before,
3031-
ST_NPoints(ST_Simplify(the_geom,0.1)) AS np01_notbadcircle,
3031+
<programlisting>SELECT ST_Npoints(the_geom) AS np_before,
3032+
ST_NPoints(ST_Simplify(the_geom,0.1)) AS np01_notbadcircle,
30323033
ST_NPoints(ST_Simplify(the_geom,0.5)) AS np05_notquitecircle,
3033-
ST_NPoints(ST_Simplify(the_geom,1)) AS np1_octagon,
3034+
ST_NPoints(ST_Simplify(the_geom,1)) AS np1_octagon,
30343035
ST_NPoints(ST_Simplify(the_geom,10)) AS np10_triangle,
30353036
(ST_Simplify(the_geom,100) is null) AS np100_geometrygoesaway
3036-
FROM
3037+
FROM
30373038
(SELECT ST_Buffer('POINT(1 3)', 10,12) As the_geom) AS foo;
30383039

30393040
np_before | np01_notbadcircle | np05_notquitecircle | np1_octagon | np10_triangle | np100_geometrygoesaway

liblwgeom/cunit/cu_lwstroke.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ static void test_lwcurve_linearize(void)
231231
*/
232232
out = lwcurve_linearize(in, 500, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
233233
str = lwgeom_to_text(out, 2);
234-
ASSERT_STRING_EQUAL(str, "LINESTRING(20 50,72 -66)");
234+
ASSERT_STRING_EQUAL(str, "LINESTRING(20 50,22 -18,72 -66)");
235235
lwfree(str);
236236
lwgeom_free(out);
237237

@@ -240,7 +240,7 @@ static void test_lwcurve_linearize(void)
240240
/*
241241
* ROBUSTNESS: big radius, small tolerance
242242
* See https://trac.osgeo.org/postgis/ticket/4058
243-
* NOTE: we are really only interested in not enterying
243+
* NOTE: we are really only interested in not entering
244244
* an infinite loop here
245245
*/
246246
toltype = LW_LINEARIZE_TOLERANCE_TYPE_MAX_DEVIATION;
@@ -250,12 +250,12 @@ static void test_lwcurve_linearize(void)
250250
"2695865.195999999996275 1125835.189000)");
251251
out = lwcurve_linearize(in, 0.0001, toltype, 0);
252252
str = lwgeom_to_text(out, 2);
253-
ASSERT_STRING_EQUAL(str, "LINESTRING(2696000 1125700,2695866 1125836)");
253+
ASSERT_STRING_EQUAL(str, "LINESTRING(2696000 1125700,2695932 1125768,2695866 1125836)");
254254
lwfree(str);
255255
lwgeom_free(out);
256256
out = lwcurve_linearize(in, 0.0001, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
257257
str = lwgeom_to_text(out, 2);
258-
ASSERT_STRING_EQUAL(str, "LINESTRING(2696000 1125700,2695866 1125836)");
258+
ASSERT_STRING_EQUAL(str, "LINESTRING(2696000 1125700,2695932 1125768,2695866 1125836)");
259259
lwfree(str);
260260
lwgeom_free(out);
261261
#ifndef SKIP_TEST_RETAIN_ANGLE
@@ -280,36 +280,36 @@ static void test_lwcurve_linearize(void)
280280

281281
in = lwgeom_from_text("CIRCULARSTRING(0 0,100 100,200 0)");
282282

283-
/* Maximum of 45 degrees, asymmetric */
283+
/* Maximum of 45 degrees per segment, asymmetric */
284284
out = lwcurve_linearize(in, M_PI / 4.0, toltype, 0);
285285
str = lwgeom_to_text(out, 2);
286286
ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,30 70,100 100,170 70,200 0)");
287287
lwfree(str);
288288
lwgeom_free(out);
289-
/* Maximum of 0 degrees (invalid) */
289+
/* Maximum of 0 degrees per segment (invalid) */
290290
cu_error_msg_reset();
291291
out = lwcurve_linearize(in, 0, toltype, 0);
292292
CU_ASSERT( out == NULL );
293293
ASSERT_STRING_EQUAL(cu_error_msg, "lwarc_linearize: max angle must be bigger than 0, got 0");
294-
/* Maximum of -2 degrees (invalid) */
294+
/* Maximum of -2 degrees per segment (invalid) */
295295
cu_error_msg_reset();
296296
out = lwcurve_linearize(in, -2, toltype, 0);
297297
CU_ASSERT( out == NULL );
298298
ASSERT_STRING_EQUAL(cu_error_msg, "lwarc_linearize: max angle must be bigger than 0, got -2");
299-
/* Maximum of 360 degrees, just return endpoints... */
299+
/* Maximum of 360 degrees per segment, just return minimum of two segments... */
300300
cu_error_msg_reset();
301301
out = lwcurve_linearize(in, M_PI*4, toltype, 0);
302302
str = lwgeom_to_text(out, 2);
303-
ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,200 0)");
303+
ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,100 100,200 0)");
304304
lwfree(str);
305305
lwgeom_free(out);
306-
/* Maximum of 70 degrees, asymmetric */
306+
/* Maximum of 70 degrees per segment, asymmetric */
307307
out = lwcurve_linearize(in, 70 * M_PI / 180, toltype, 0);
308308
str = lwgeom_to_text(out, 2);
309309
ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,66 94,176 64,200 0)");
310310
lwfree(str);
311311
lwgeom_free(out);
312-
/* Maximum of 70 degrees, symmetric */
312+
/* Maximum of 70 degrees per segment, symmetric */
313313
out = lwcurve_linearize(in, 70 * M_PI / 180, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
314314
str = lwgeom_to_text(out, 2);
315315
ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,50 86,150 86,200 0)");

0 commit comments

Comments
 (0)