[postgis-users] Topology: Simplifying Coastlines with Islands

Sandro Santilli strk at keybit.net
Mon May 28 03:39:48 PDT 2012


On Mon, May 28, 2012 at 11:56:13AM +0200, Michiel J. van Heek wrote:

> Sandro,
> 
> Based on your suggestions, I changed the script in three ways (see
> below for the result):
> 
> 1. The number of iterations is now a parameter and running down the
> tolerance uses linear steps for each iteration (0.5, 0.45, 0.4,
> 0.35, etc.). The division by 2 solution (0.5, 0.25, 0.125, etc.) put
> a heavy weight on the lower tolerances, whereas it is often
> worthwile to also try higher tolerances (between initial tolerance
> and half of the initial tolerance).
> 
> 2. If an iteration fails because of "not simple" the same iteration
> is run again, but with "PreserveTopology" now.
> 
> 3. When all iterations fail, the function returns NULL now, and does
> not throw an exception. It is now possible to find "unwilling" edges
> by running:
> 
> SELECT *
> FROM (
>     SELECT
>         edge_id,
>         SimplifyEdgeGeom('countries_topology_4', edge_id, 0.5) AS tolerance
>     FROM countries_topology_4.edge
> ) AS foo
> WHERE (tolerance IS NULL);
> 
> Also, I removed the STABLE attribute, because the funtion *does*
> make changes to the database.

Good work ! Maybe make the "curve not simple" handling more tolerant of
eventual changes in the exception text (only look for "not simple"?).

How do your country boundaries look now ? :)

--strk;

  ,------o-. 
  |   __/  |    Delivering high quality PostGIS 2.0 !
  |  / 2.0 |    http://strk.keybit.net - http://vizzuality.com
  `-o------'


> CREATE OR REPLACE FUNCTION SimplifyEdgeGeom(topology_param text,
> edge_id_param integer, tolerance_param double precision,
> num_iterations_param integer DEFAULT 10) RETURNS double precision AS
> $BD$
> DECLARE
>     i integer := 1;
>     xi text := '';
>     tolerance_var double precision := tolerance_param;
>     sql_var text;
> BEGIN
>     WHILE (i <= num_iterations_param) LOOP
>         sql_var := 'SELECT topology.ST_ChangeEdgeGeom(' ||
> quote_literal(topology_param) || ', ' || edge_id_param
>           || ', ST_Simplify' || xi || '(geom, ' || tolerance_var || ')) FROM '
>           || quote_ident(topology_param) || '.edge WHERE edge_id = '
> || edge_id_param;
>         BEGIN
>             RAISE DEBUG 'Running %', sql_var;
>             EXECUTE sql_var;
> 
>             RETURN tolerance_var;
>         EXCEPTION
>             WHEN OTHERS THEN
>                 RAISE WARNING 'Simplification of edge % failed in
> iteration %_%, with tolerance %: %',
>                     edge_id_param, i, xi, tolerance_var, SQLERRM;
> 
>                 IF (SQLERRM = 'SQL/MM Spatial exception - curve not
> simple') AND (xi = '') THEN
>                     xi := 'PreserveTopology';
>                 ELSE
>                     i := i + 1;
>                     xi := '';
>                     tolerance_var := tolerance_var -
> (tolerance_param / num_iterations_param);
>                 END IF;
>             END;
>         -- END EXCEPTION
>     END LOOP;
> 
>     RETURN NULL;
> END;
> $BD$ LANGUAGE 'plpgsql' STRICT;



More information about the postgis-users mailing list