/* This file is part of the book titled: * "TALLERES PRÁCTICOS DE INICIACIÓN A POSTGIS (LINUX Y POSTGRESQL)". * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * For more information, contact: * * Jose Carlos Martinez Llario * * Universidad Politecnica de Valencia * Deparment of Cartographic Engineering, Geodesy and Photogrammetry * Camino de Vera, s/n. 46022 Valencia (Spain) * email: jomarlla@cf.upv.es * web: http://cartosig.upv.es * Tel. +34 96 387 70 07 Ext. 75599 * Fax. +34 96 387 75 59 */ /* Funciones PL/pgSQL implementadas: pgCreaCapa (tnombreTabla, tipoGeometria) [SRID=-1, nombreColumnaGeometria = 'geom'] pgCreaCapa (nombreTabla, tipoGeometria, SRID) [nombreColumnaGeometria = 'geom'] pgCreaCapa (tnombreTabla, tipoGeometria, SRID, nombreColumnaGeometria) Def: Crea una capa PostGIS segun los argumentos especificados. Esta funcion llama a addgeometrycolum de PostGIS. Solo funciona en el schema por defecto 'public'. Ademas añade un campo de clave primaria denominado GID que es de tipo autonumerico de postgreSQL (serial). pgBorraCapa (nombreTabla) [nombreColumnaGeometria = 'geom'] pgBorraCapa (nombreTabla, nombreColumnaGeometria) Def: Elimina la capa PostGIS especificada. Para ello llama al metodo dropgeometrycolumn de PostGIS y borra la tabla. Solo funciona en el schema por defecto 'public'. pgExtract (geometria, dimension) Def: Esta función extrae los elemetos individuales integrantes de la geometria pasada como argumento y devuelve unicamente los que tengan como dimension la especifica como segundo argumento. En el caso que la geometria pasada como argumento no contenga ninguna geometria de la dimension especificada devuelve nulo, en caso contrario siempre devuelve una geometria de tipo MULTI. Esta funcion sirve para extraer de geometrias de tipo GEOMETRYCOLLECTION las geometrias de la dimension interesada. pgIntersection (geometria1, geometria2) Def: Devuelve la interseccion superficial de las dos geometrias que toma como argumento, Devuelve unicamente las entidades superficiales de la intersección en elementos de tipo multipoligono. Esta funcion se utiliza para la creación del agregado pgAGGIntersection pgAGGIntersection (geometria) Def: Agregado que realiza la intersección entre las entidades que se van pasando como argumento. Devuelve unicamente las entidades superficiales de la intersección en elementos de tipo multipoligono */ /* Este fichero es necesario ejecutarlo dentro de una base de datos espacial PostGIS. Para ser capaz de definir una funcion el usuario de la base de datos debe tener permisos de USO sobre el lenguaje. Ademas el lenguaje PL/pgSQL debe estar instalado en la base de datos (cuando se crea una base de datos espacial PostGIS esto es un paso necesario y se realiza con la orden CREATE LANGUAGE con lo cual no es necesario realizarlo aqui Este fichero se debe ejecutar sobre la base de datos espacial en la cual se van a utilizar las funciones definidas en el. */ BEGIN TRANSACTION; CREATE OR REPLACE FUNCTION pgCreaCapa (text,text) RETURNS text AS $$ DECLARE ret text; BEGIN SELECT pgCreaCapa ($1,$2,'') INTO ret; RETURN ret; END; $$ LANGUAGE 'plpgsql' WITH (isstrict); CREATE OR REPLACE FUNCTION pgCreaCapa (text,text,text) RETURNS text AS $$ DECLARE ret text; BEGIN SELECT pgCreaCapa ($1,$2,$3,'geom') INTO ret; RETURN ret; END; $$ LANGUAGE 'plpgsql' WITH (isstrict); CREATE OR REPLACE FUNCTION pgCreaCapa (text,text,text,text) RETURNS text AS $$ DECLARE tabla alias for $1; tipogeom alias for $2; sridtmp alias for $3; nombregeomtmp alias for $4; srid text; nombregeom text; BEGIN /* Crea una tabla espacial de PostGIS de nombre $1, campo de geometria $4, y tipo de geometria $2. y srid $3. Si srid esta vacio por defecto sera -1 Considera Dimensiones = 2 */ /* Compruebo si el tipo de geometría es válido */ IF ( not ( (tipogeom ='GEOMETRY') or (tipogeom ='GEOMETRYCOLLECTION') or (tipogeom ='POINT') or (tipogeom ='MULTIPOINT') or (tipogeom ='POLYGON') or (tipogeom ='MULTIPOLYGON') or (tipogeom ='LINESTRING') or (tipogeom ='MULTILINESTRING')) ) THEN RAISE EXCEPTION 'Nombre de tipo no válido - los tipos válidos son: GEOMETRY, GEOMETRYCOLLECTION, POINT, MULTIPOINT, POLYGON, MULTIPOLYGON, LINESTRING, or MULTILINESTRING '; RETURN 'fallo'; END IF; /* Miro si he puesto un argumento vacio */ IF tabla = '' THEN RAISE EXCEPTION 'Nombre de tabla vacio'; RETURN 'fallo'; END IF; /* Pone valor por defecto a SRID si es el caso */ srid := sridtmp; IF srid = '' THEN srid := '-1'; END IF; /* Miro si la tabla ya existe */ PERFORM * FROM pg_tables WHERE tablename = tabla; IF FOUND THEN RAISE EXCEPTION 'La tabla ya existe'; RETURN 'fallo'; END IF; /* Pone valor por defecto en campo de geometría si es el caso */ nombregeom := nombregeomtmp; IF (nombregeom = '') THEN nombregeom := 'geom'; END IF; EXECUTE 'CREATE TABLE ' || quote_ident(tabla) || '(gid serial)'; EXECUTE 'SELECT ADDGEOMETRYCOLUMN (' || quote_literal('') || ',' || quote_literal(tabla) || ',' || quote_literal(nombregeom) || ',' || srid || ',' || quote_literal(tipogeom) || ',2)'; EXECUTE 'ALTER TABLE ONLY ' || quote_ident (tabla) || ' ADD CONSTRAINT ' || quote_ident(tabla) || '_pkey PRIMARY KEY (gid)'; RETURN 'La tabla se ha creado correctamente'; END; $$ LANGUAGE 'plpgsql' WITH (isstrict); CREATE OR REPLACE FUNCTION pgBorraCapa (text) RETURNS text AS $$ DECLARE ret text; BEGIN SELECT pgBorraCapa ($1,'') INTO ret; RETURN ret; END; $$ LANGUAGE 'plpgsql' WITH (isstrict); CREATE OR REPLACE FUNCTION pgBorraCapa (text,text) RETURNS text AS $$ DECLARE tabla alias for $1; nombregeomtmp alias for $2; nombregeom text; BEGIN /* Borrra una tabla espacial de PostGIS de nombre $1 y con el nombre del campo de geometria $2 */ /* Miro si he puesto un argumento vacio */ IF tabla = '' THEN RAISE EXCEPTION 'Nombre de tabla vacio'; RETURN 'fallo'; END IF; /* Miro si la tabla ya existe */ PERFORM * FROM pg_tables WHERE tablename = tabla; IF NOT FOUND THEN RAISE EXCEPTION 'La tabla no existe'; RETURN 'fallo'; END IF; /* Pone valor por defecto en campo de geometría si es el caso */ nombregeom := nombregeomtmp; IF (nombregeom = '') THEN nombregeom := 'geom'; END IF; EXECUTE 'SELECT DROPGEOMETRYCOLUMN (' || quote_literal('') || ',' || quote_literal(tabla) || ',' || quote_literal(nombregeom) || ')'; EXECUTE 'DROP TABLE ' || quote_ident(tabla); RETURN 'La tabla se ha borrado correctamente'; END; $$ LANGUAGE 'plpgsql' WITH (isstrict); CREATE OR REPLACE FUNCTION pgExtract (geometry,integer) RETURNS geometry AS $$ DECLARE geomin alias for $1; dim alias for $2; tipogeom text; gn geometry; gt text; gnres geometry; geomsimples geometry[]; fila RECORD; BEGIN tipogeom := geometrytype(geomin); IF (tipogeom = 'POLYGON' AND dim = 2) THEN RETURN multi (geomin); END IF; IF (tipogeom = 'MULTIPOLYGON' AND dim = 2) THEN RETURN geomin; END IF; IF (tipogeom = 'LINESTRING' AND dim = 1) THEN RETURN multi (geomin); END IF; IF (tipogeom = 'MULTILINESTRING' AND dim = 1) THEN RETURN geomin; END IF; IF (tipogeom = 'POINT' AND dim = 0) THEN RETURN multi (geomin); END IF; IF (tipogeom = 'MULTIPOINT' AND dim = 0) THEN RETURN geomin; END IF; IF (tipogeom != 'GEOMETRYCOLLECTION') THEN RETURN gnres; END IF; FOR fila IN SELECT geom(dump(geomin)) LOOP gn := fila.geom; gt := geometrytype(gn); IF ((dim = 2 AND gt = 'POLYGON') OR (dim = 1 AND gt = 'LINESTRING') OR (dim = 0 AND gt = 'POINT')) THEN geomsimples := geom_accum (geomsimples, gn); END IF; END LOOP; gnres := collect_garray (geomsimples); RETURN gnres; END; $$ LANGUAGE 'plpgsql' WITH (isstrict); CREATE OR REPLACE FUNCTION pgIntersection (geometry,geometry) RETURNS geometry AS $$ DECLARE geom1 alias for $1; geom2 alias for $2; gint geometry; BEGIN gint := intersection (geom1, geom2); gint := pgExtract (gint, 2); RETURN gint; END; $$ LANGUAGE 'plpgsql' WITH (isstrict); DROP AGGREGATE IF EXISTS pgAGGIntersection (geometry); CREATE AGGREGATE pgAGGIntersection ( sfunc = pgIntersection, basetype = geometry, stype = geometry); END TRANSACTION;