Skip to content

Commit

Permalink
Impose min number of segments per arc during linearization
Browse files Browse the repository at this point in the history
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 #320




git-svn-id: http://svn.osgeo.org/postgis/trunk@16998 b70326c6-7e19-0410-871a-916f4a2858ee
  • Loading branch information
dbaston committed Nov 8, 2018
1 parent 73f8752 commit b6eb7ec
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 130 deletions.
1 change: 1 addition & 0 deletions doc/introduction.xml
Expand Up @@ -317,6 +317,7 @@
<listitem><simpara><ulink url="https://www.camptocamp.com">Camptocamp</ulink></simpara></listitem>
<listitem><simpara><ulink url="https://carto.com">Carto</ulink></simpara></listitem>
<listitem><simpara><ulink url="https://www.boston.gov">City of Boston (DND)</ulink></simpara></listitem>
<listitem><simpara><ulink url="https://www.hel.fi">City of Helsinki</ulink></simpara></listitem>
<listitem><simpara><ulink url="https://blog.cleverelephant.ca">Clever Elephant Solutions</ulink></simpara></listitem>
<listitem><simpara><ulink url="https://www.alveo.coop">Cooperativa Alveo</ulink></simpara></listitem>
<listitem><simpara><ulink url="http://www.elecnor-deimos.com">Deimos Space</ulink></simpara></listitem>
Expand Down
9 changes: 5 additions & 4 deletions doc/reference_processing.xml
Expand Up @@ -976,6 +976,7 @@ Supported bits are:

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

<para>&sfs_compliant;</para>
<para>&sqlmm_compliant; SQL-MM 3: 7.1.7</para>
Expand Down Expand Up @@ -3027,13 +3028,13 @@ select ST_WrapX(the_geom, -30, 360);
<refsection>
<title>Examples</title>
<para>A circle simplified too much becomes a triangle, medium an octagon, </para>
<programlisting>SELECT ST_Npoints(the_geom) AS np_before,
ST_NPoints(ST_Simplify(the_geom,0.1)) AS np01_notbadcircle,
<programlisting>SELECT ST_Npoints(the_geom) AS np_before,
ST_NPoints(ST_Simplify(the_geom,0.1)) AS np01_notbadcircle,
ST_NPoints(ST_Simplify(the_geom,0.5)) AS np05_notquitecircle,
ST_NPoints(ST_Simplify(the_geom,1)) AS np1_octagon,
ST_NPoints(ST_Simplify(the_geom,1)) AS np1_octagon,
ST_NPoints(ST_Simplify(the_geom,10)) AS np10_triangle,
(ST_Simplify(the_geom,100) is null) AS np100_geometrygoesaway
FROM
FROM
(SELECT ST_Buffer('POINT(1 3)', 10,12) As the_geom) AS foo;

np_before | np01_notbadcircle | np05_notquitecircle | np1_octagon | np10_triangle | np100_geometrygoesaway
Expand Down
22 changes: 11 additions & 11 deletions liblwgeom/cunit/cu_lwstroke.c
Expand Up @@ -231,7 +231,7 @@ static void test_lwcurve_linearize(void)
*/
out = lwcurve_linearize(in, 500, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
str = lwgeom_to_text(out, 2);
ASSERT_STRING_EQUAL(str, "LINESTRING(20 50,72 -66)");
ASSERT_STRING_EQUAL(str, "LINESTRING(20 50,22 -18,72 -66)");
lwfree(str);
lwgeom_free(out);

Expand All @@ -240,7 +240,7 @@ static void test_lwcurve_linearize(void)
/*
* ROBUSTNESS: big radius, small tolerance
* See https://trac.osgeo.org/postgis/ticket/4058
* NOTE: we are really only interested in not enterying
* NOTE: we are really only interested in not entering
* an infinite loop here
*/
toltype = LW_LINEARIZE_TOLERANCE_TYPE_MAX_DEVIATION;
Expand All @@ -250,12 +250,12 @@ static void test_lwcurve_linearize(void)
"2695865.195999999996275 1125835.189000)");
out = lwcurve_linearize(in, 0.0001, toltype, 0);
str = lwgeom_to_text(out, 2);
ASSERT_STRING_EQUAL(str, "LINESTRING(2696000 1125700,2695866 1125836)");
ASSERT_STRING_EQUAL(str, "LINESTRING(2696000 1125700,2695932 1125768,2695866 1125836)");
lwfree(str);
lwgeom_free(out);
out = lwcurve_linearize(in, 0.0001, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
str = lwgeom_to_text(out, 2);
ASSERT_STRING_EQUAL(str, "LINESTRING(2696000 1125700,2695866 1125836)");
ASSERT_STRING_EQUAL(str, "LINESTRING(2696000 1125700,2695932 1125768,2695866 1125836)");
lwfree(str);
lwgeom_free(out);
#ifndef SKIP_TEST_RETAIN_ANGLE
Expand All @@ -280,36 +280,36 @@ static void test_lwcurve_linearize(void)

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

/* Maximum of 45 degrees, asymmetric */
/* Maximum of 45 degrees per segment, asymmetric */
out = lwcurve_linearize(in, M_PI / 4.0, toltype, 0);
str = lwgeom_to_text(out, 2);
ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,30 70,100 100,170 70,200 0)");
lwfree(str);
lwgeom_free(out);
/* Maximum of 0 degrees (invalid) */
/* Maximum of 0 degrees per segment (invalid) */
cu_error_msg_reset();
out = lwcurve_linearize(in, 0, toltype, 0);
CU_ASSERT( out == NULL );
ASSERT_STRING_EQUAL(cu_error_msg, "lwarc_linearize: max angle must be bigger than 0, got 0");
/* Maximum of -2 degrees (invalid) */
/* Maximum of -2 degrees per segment (invalid) */
cu_error_msg_reset();
out = lwcurve_linearize(in, -2, toltype, 0);
CU_ASSERT( out == NULL );
ASSERT_STRING_EQUAL(cu_error_msg, "lwarc_linearize: max angle must be bigger than 0, got -2");
/* Maximum of 360 degrees, just return endpoints... */
/* Maximum of 360 degrees per segment, just return minimum of two segments... */
cu_error_msg_reset();
out = lwcurve_linearize(in, M_PI*4, toltype, 0);
str = lwgeom_to_text(out, 2);
ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,200 0)");
ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,100 100,200 0)");
lwfree(str);
lwgeom_free(out);
/* Maximum of 70 degrees, asymmetric */
/* Maximum of 70 degrees per segment, asymmetric */
out = lwcurve_linearize(in, 70 * M_PI / 180, toltype, 0);
str = lwgeom_to_text(out, 2);
ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,66 94,176 64,200 0)");
lwfree(str);
lwgeom_free(out);
/* Maximum of 70 degrees, symmetric */
/* Maximum of 70 degrees per segment, symmetric */
out = lwcurve_linearize(in, 70 * M_PI / 180, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
str = lwgeom_to_text(out, 2);
ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,50 86,150 86,200 0)");
Expand Down

0 comments on commit b6eb7ec

Please sign in to comment.