[postgis-users] Topology: Simplifying Coastlines with Islands
Michiel J. van Heek
michielvanheek at nine-e.org
Mon May 28 02:56:13 PDT 2012
Quoting Sandro Santilli <strk at keybit.net>:
> On Sat, May 26, 2012 at 10:37:14PM +0200, Michiel J. van Heek wrote:
>
>> So, why not use ST_SimplifyPreserveTopology by default? Or is that
>> function generally a lot slower than ST_Simplify?
>
> Is a lot slower.
> But the script was just an example, you can tweak the heuristic to
> parse the error message and use *PreserveTopology for the 'non-simple'
> case, rather than reduce the tolerance. Also, you may want to reduce
> less than 1/2. You could have got away with a 0.45. Finally you could
> just let that edge go in the first iteration and run a second time.
> Some times just letting the function run for other edges automatically
> removes the obstacles for next iteration...
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.
Michiel
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