pggeodb.nancy.inra.fr/db_toff - db_toff on pggeodb.nancy.inra.fr
Previous topic Chapter index Next topic

Function: st_simplify

 

 

Schema

topology

 

Owner

postgres

 

Descriptions

args: geomA, tolerance - Returns a "simplified" geometry version of the given TopoGeometry using the Douglas-Peucker algorithm.

 

Options

Option

Value

Returns

public.geometry

Language

plpgsql

Parameters

tg topology.topogeometry

tolerance double precision

 

Definition

CREATE OR REPLACE FUNCTION topology.st_simplify (
 tg topology.topogeometry,
 tolerance double precision
)
RETURNS public.geometry AS
$span$
DECLARE

 topology_info RECORD;
 layer_info RECORD;
 child_layer_info RECORD;
 geom geometry;
 sql TEXT;
BEGIN

 -- Get topology information
 SELECT id, name FROM topology.topology
   INTO topology_info
   WHERE id = tg.topology_id;
 IF NOT FOUND THEN
     RAISE EXCEPTION
'No topology with id "%" in topology.topology', tg.topology_id;
 END IF;

 -- Get layer info
 SELECT * FROM topology.layer
   WHERE topology_id = tg.topology_id
   AND layer_id = tg.layer_id
   INTO layer_info;
 IF NOT FOUND THEN
   RAISE EXCEPTION
'Could not find TopoGeometry layer % in topology %', tg.layer_id, tg.topology_id;
 END IF;

 --
 -- If this feature layer is on any level > 0 we will
 -- compute the topological union of all simplified child
 -- features in fact recursing.
 --

 IF layer_info.level > 0 THEN -- {

   -- Get child layer info

   SELECT * FROM topology.layer WHERE layer_id = layer_info.child_id
     AND topology_id = tg.topology_id
     INTO child_layer_info;
   IF NOT FOUND THEN
     RAISE EXCEPTION
'Invalid layer % in topology % (unexistent child layer %)', tg.layer_id, tg.topology_id, layer_info.child_id;
   END IF;

   sql := 'SELECT st_multi(st_union(topology.ST_Simplify('
     || quote_ident(child_layer_info.feature_column)
     || ',' || tolerance || '))) as geom FROM '
     || quote_ident(child_layer_info.schema_name) || '.'
     || quote_ident(child_layer_info.table_name)
     || ', ' || quote_ident(topology_info.name) || '.relation pr'
     || ' WHERE '
     || ' pr.topogeo_id = ' || tg.id
     || ' AND '
     || ' pr.layer_id = ' || tg.layer_id
     || ' AND '
     || ' id('||quote_ident(child_layer_info.feature_column)
     || ') = pr.element_id '
     || ' AND '
     || 'layer_id('||quote_ident(child_layer_info.feature_column)
     || ') = pr.element_type ';
   RAISE DEBUG '%', sql;
   EXECUTE sql INTO geom;

 ELSIF tg.type = 3 THEN -- [multi]polygon -- }{

   -- TODO: use ST_GetFaceEdges
   -- TODO: is st_unaryunion needed?

   sql := 'SELECT st_multi(st_unaryunion(ST_BuildArea(ST_Node(ST_Collect(ST_Simplify(geom, '
     || tolerance || ')))))) as geom FROM '
     || quote_ident(topology_info.name)
     || '.edge_data e, '
     || quote_ident(topology_info.name)
     || '.relation r WHERE ( e.left_face = r.element_id'
     || ' OR e.right_face = r.element_id )'
     || ' AND r.topogeo_id = ' || tg.id
     || ' AND r.layer_id = ' || tg.layer_id
     || ' AND element_type = 3 ';
   RAISE DEBUG '%', sql;
   EXECUTE sql INTO geom;


 ELSIF tg.type = 2 THEN -- [multi]line -- }{

   sql :=
     'SELECT st_multi(ST_LineMerge(ST_Node(ST_Collect(ST_Simplify(e.geom,'
     || tolerance || '))))) as g FROM '
     || quote_ident(topology_info.name) || '.edge e, '
     || quote_ident(topology_info.name) || '.relation r '
     || ' WHERE r.topogeo_id = ' || tg.id
     || ' AND r.layer_id = ' || tg.layer_id
     || ' AND r.element_type = 2 '
     || ' AND abs(r.element_id) = e.edge_id';
   EXECUTE sql INTO geom;

 ELSIF tg.type = 1 THEN -- [multi]point -- }{

   -- Can't simplify points...

   geom := topology.Geometry(tg);

 ELSIF tg.type = 4 THEN -- mixed collection -- }{

  sql := 'WITH areas AS ( '
     || 'SELECT st_multi(st_union(ST_BuildArea(ST_Node(ST_Collect(ST_Simplify(geom, '
     || tolerance || ')))) as geom FROM '
     || quote_ident(topology_info.name)
     || '.edge_data e, '
     || quote_ident(topology_info.name)
     || '.relation r WHERE ( e.left_face = r.element_id'
     || ' OR e.right_face = r.element_id )'
     || ' AND r.topogeo_id = ' || tg.id
     || ' AND r.layer_id = ' || tg.layer_id
     || ' AND element_type = 3 ), '
     || 'lines AS ( '
     || 'SELECT st_multi(ST_LineMerge(ST_Collect(ST_Simplify(e.geom,'
     || tolerance || ')))) as g FROM '
     || quote_ident(topology_info.name) || '.edge e, '
     || quote_ident(topology_info.name) || '.relation r '
     || ' WHERE r.topogeo_id = ' || tg.id
     || ' AND r.layer_id = ' || tg.layer_id
     || ' AND r.element_type = 2 '
     || ' AND abs(r.element_id) = e.edge_id ), '
     || ' points as ( SELECT st_union(n.geom) as g FROM '
     || quote_ident(topology_info.name) || '.node n, '
     || quote_ident(topology_info.name) || '.relation r '
     || ' WHERE r.topogeo_id = ' || tg.id
     || ' AND r.layer_id = ' || tg.layer_id
     || ' AND r.element_type = 1 '
     || ' AND r.element_id = n.node_id ), '
     || ' un as ( SELECT g FROM areas UNION ALL SELECT g FROM lines '
     || '          UNION ALL SELECT g FROM points ) '
     || 'SELECT ST_Multi(ST_Collect(g)) FROM un';
   EXECUTE sql INTO geom;

 ELSE -- }{

   RAISE EXCEPTION 'Invalid TopoGeometries (unknown type %)', tg.type;

 END IF; -- }

 RETURN geom;

END
$span$
LANGUAGE
'plpgsql'
VOLATILE
RETURNS NULL ON NULL INPUT
SECURITY INVOKER
COST
100;

COMMENT ON FUNCTION topology.st_simplify(tg topology.topogeometry, tolerance double precision)
IS 'args: geomA, tolerance - Returns a "simplified" geometry version of the given TopoGeometry using the Douglas-Peucker algorithm.';

This file was generated with SQL Manager for PostgreSQL (www.pgsqlmanager.com) at 13/03/2014 13:23
Previous topic Chapter index Next topic