9_SQL_Espacial

download 9_SQL_Espacial

If you can't read please download the document

Transcript of 9_SQL_Espacial

MANUALDEL CURSO BASES DE DATOS GEOGRFICAS

Alvaro Zabala Ordez - Francisco de Borja Maas lvarez

Versin 1.0 - Revisado el 3 de Octubre de 2012

Estaobra est licenciada bajo una Licencia Creative Commons Atribucin 3.0 Unported.

Bajoesta licencia, usted es libre de compartir - copiar, distribuir, ejecutar y comunicar pblicamente, hacer obras derivadas y hacer un uso comercial de esta obra.Lanica condicin que usted debe cumplir es la de respetar la Atribucin: debe reconocer loscrditos de la obra de la siguiente manera:

Manual del curso Bases de Datos Geogrficas. Alvaro Zabala y Borja Maas. http://www.lookingformaps.com/curso-postgis

Puede leer la licencia en http://creativecommons.org/licenses/by/3.0/

BLOQUE IIBASES DEDATOS ESPACIALES.9.SQL espaciala) SQL ESPACIAL EN POSTGIS

Como ya hemos visto, SQL (Structured Query Language) es un lenguaje declarativo de acceso a bases de datos relacionales, mediante el cual pueden manipularse la informacin que almacena. Se compone de:

Lenguaje de definicin de datos, mediante el cual se definen elementos y las relaciones entre los mismos.

Lenguaje de manipulacin de datos, para crear, modificar y borrar elementos de la base de datos.

Lenguaje de control de datos, para controlarel acceso a los mismos.

Entre las operaciones incluidas en el lenguaje de manipulacin de datos se encuentran lasconsultas. Ejecutadas mediante la clusula SELECT, responden a una estructura base como la siguiente:

SELECT [DISTINCT] columna1 [ASalias1] [, columna2, ...]FROM tabla [, tabla2, ...]WHERE condicion1[AND condicion2 ...][OR condicion3...][GROUP BY columna][ORDER BY columna];

Que puede ser ampliada con otras clusulas y operadores existentes.

Adicionalmente, pueden emplearse unaserie defuncionesque vienen implementadas en los SGBD. Precisamente los SGBD con soporte espacial tienen definidos, adems de todos los tipos de datos necesarios, multitud de funciones para el tratamiento de la informacin espacial. Ello nos va apermitir, mediante consultas SQL, dar respuestas a cuestiones como:

Qupozos se encuentran a menos de 2km de un ro?

Cul es la longitud total de la autopista A-92?

Cules son los ncleos de poblacin con mayor rea?

Qucasas se encuentran en laribera de un ro?

Como vemos, son consultas en las que existe una relacin espacial entre los elementos que intervienen. Ms adelante veremos ejemplos concretos de algunas de estas funciones.Vamos a repasar las principales funciones espaciales de Postgis vistas en mdulos anteriores, entrando un poco ms en detalle de las particularidades de cada una, y con algunos ejemplos de uso.

Tipos bsicos y envelopes

geometry

geography

Son los dos tipos bsicos que Postgis ofrece para almacenar informacinespacial. Como ya vimos, el primero representa el tipo Geometra OGC que se aplica en sistemas de coordenadas plano, mientras que el segundo, ms reciente, utiliza un sistema de coordenadas geodsico, soportando concreta y nicamente el SRID:4326 (WGS84 longitud/latitud).

Hay que valorar siempre el tratamiento que queremos dar a nuestra informacin espacial y las caractersticas de la misma para decidir cul de los dos tipos usar. En cualquier caso, el tipo geography admite conversin mediantecasta geography.

box2d

box3d

Representan boxes o cajas, es decir, los envelopes o rectngulos formados por coordenadas xmin, ymin, xmax, ymax en el caso de 2d, o xmin, ymin, zmin, xmax, ymax, zmax en el caso de 3d. Se usan para representar el envelope en el queencaja una o varias geometras.

Las funciones:

box2dBox2D(geometry geomA);box3dBox3D(geometry geomA);

Reciben una geometra, y devuelven el box correspondiente. Por ejemplo, la consulta:

SELECT Box2D(geom) from municipios WHERE municipio like 'Bormujos';

Devuelve el envelope del municipio de Bormujos:

BOX(321948.906139399 4122221.99989328,327193.812381747 4126534.99989519)

Box2d del municipio

Otra funcin que nos permite obtener el envelope de una geometra esST_Envelope, que adems cumplecon la especificacin de OGC. En este caso, obtenemos directamente un objeto geometry formado por las cuatro coordenadas del envelope:

"POLYGON((223707.499921379 4137757.00005855,223707.499921379 4142171.99988734,229437.203066569 4142171.99988734,229437.203066569 4137757.00005855,223707.499921379 4137757.00005855))"

funciones de manipulacin

AddGeometryColumn

DropGeometryColumn

Estas funciones permiten aadir y quitar una columna de tipo geometry a una tabla. No es la nica manera, ya que en lapropia sentencia CREATE de una tabla se puede especificar la columna geometry como una ms. Sin embargo estas funciones actualizan automticamente la vista GEOMETRY_COLUMNS con la informacin de la columna geometry aadida. Adems, implementan la especificacin SFS de Open GIS:

textAddGeometryColumn(varchar table_name, varchar column_name, integer srid, varchar type, integer dimension, boolean use_typmod=true);

textDropGeometryColumn(varchar table_name, varchar column_name);

Las siguientes sentenciascrean una tabla y le aaden una columna de tipo geometry:

CREATE TABLE mi_tabla(id integer NOT NULL,nombre character varying(256))

SELECT AddGeometryColumn ('public','mi_tabla','geom',23030,'POINT',2);

Podemos comprobar que la vista GEOMETRY_COLUMNS contiene despus de ejecutarlas informacin sobre la columna aadida:

SELECT f_geometry_column, type, srid, coord_dimensionFROM geometry_columnsWHERE f_table_name = 'mi_tabla';

Devuelve: "geom" ; "POINT" ; 23030 ; 2

PostGIS_Version

PostGIS_Full_Version

Nos muestran informacin acerca de la versin de Postgis instalada, en menor o mayor detalle.

SELECT PostGIS_Version();

UpdateGeometrySRID

Asigna el SRID especificado a todas las geometras de una tabla. Se encarga adems de actualizar la tablaGEOMETRY_COLUMNS con el nuevo valor del SRID. Por ejemplo, la siguiente sentencia actualizara el SRID de la columna geom de la tabla municipios a 23030:select UpdateGeometrySRID('municipios','geom',23030);

Constructores de geometras

ST_GeomFromText

ST_GeomFromEWKT

ST_GeomFromWKB

ST_GeomFromEWKB

ST_GeomFromGML

ST_GeomFromKML

Permiten construir objetos de tipo geometry, partiendo en cada caso de datos expresados por un formato distinto, tal como puede deducirse de sus nombres: texto, WKB, WKT, etc.

Existen algunas funciones que son meros alias de stas, o tienen una funcionalidad similar pero con algunas peculiaridades que las hacen ms eficientes para un determinado tipo de situaciones, aunque dejan de cumplir la especificacin OGC. Por ejemplo, la funcin ST_MakePoint recibe coordenadas geogrficas y devuelve el geometry correspondiente.

algunos ejemplos:

SELECT ST_GeomFromText('POINT(-71.064544 42.28787)', 4326);

SELECT ST_GeomFromKML('
23.734154,37.980107,0 ');

A la hora de especificar las coordenadas de las geometras, hay que cumplir las condiciones particulares de cada tipo: por ejemplo, para definir un polgono, debemos especificar un mnimo de 3 coordenadas, teniendo adems que ser iguales la primera y la ltima. En caso de no cumplirlas, el propio Postgis nos informar de la causa del error.

Es posible, dada una geometra en algno de los formatos anteriores, usar algunas de las funciones generadoras de geometra, que traducen de un formato a otro. Son las funciones:

ST_AsBinary, devuelve WKB sin el SRID.

ST_AsEWKB, devuelve EWKB, que incluye el SRID

ST_AsEWKT, devuelve EWKT, con el SRID.

ST_AsGeoJSON, devuelve la geometra como GeoJSON.

ST_AsGML, devuelve el GML en su versin 2 o 3.

ST_AsKML, genera el KML correspondiente.

ST_AsSVG, devuelve el SVG.

ST_AsText, devuelve ela representacin WKT sin el SRID.

ST_AsLatLon, devuelve el punto en grados, minutos y segundos.

Por ejemplo, las siguientes sentencias generan distintas representacines de la geometra del municipio de Sevilla:

SELECT ST_AsGML(geom) from municipios WHERE municipio like 'Sevilla';

231406.70308341281,4132783.999884665...

SELECT ST_AsSVG(geom) from municipios WHERE municipio like 'Sevilla';

"M 231406.70308341281 -4132783.999884665 L 231313.50010584135 ...

Informacin sobregeometras

GeometryType

Devuelve el tipo de la geometra, en forma de texto.Por ejemplo:

SELECT GeometryType(geom) from carreteras where gid=1

Devuelve MULTILINESTRING, que es el tipo de geometra que tienen los elementos de nuestra tabla de carreteras.

ST_IsValid

Indica si la geometra es vlida, si est bien formada. Por ejemplo, teniendo en cuenta queun polgono, para que est bien formado, no debe tener intersecciones consigo mismo, la sentencia:

SELECT ST_IsValid(ST_GeomFromText('POLYGON((75.15 29.53,77 29,77.6 29.5, 75.15 29.53))'))

Debe devolver t (true), mientras que si la modificamos y hacemos que tenga dos vrtices con las mismas coordenadas:

SELECT ST_IsValid(ST_GeomFromText('POLYGON((75.15 29.53,77 29,77.6 29.5,77 29 ,75.15 29.53))'))

Postgis nos dice que no es vlido (f). Esta funcin nos permite descartar aquellas geometras no vaidas, pero si adems queremos saber qu fallos tienen, podemos llamar a la funcinST_IsValidReason, que nos describe el motivo por el que la geometrano es vlida. En el caso anterior, obtendramos:

SELECT ST_IsValidReason(ST_GeomFromText('POLYGON((75.15 29.53,77 29,77.6 29.5,77 29 ,75.15 29.53))'))

"Self-intersection[75.15 29.53]"

ST_NPoints

Nos devuelve el nmero de puntos de una geometra. Estil ya que algunos procesos espaciales pueden ser especialmente pesados en geometras con un alto nmero de puntos.

SELECT ST_NPoints(geom) from municipios WHERE municipio like 'Sevilla';

ST_SRID

Nos indica el SRID de la geometra:

SELECT ST_SRID(geom) from CARRETERAS WHERE gid=1;

Devuelve 23030. El SRID debe coincidir con algno de los que Postgis tenga definidos en la tabla spatial_ref_sys.

ST_X, ST_XMax, ST_XMin, ST_Y, ST_YMax, ST_YMin devuelven las coordenadas x o y, mnimas o mximas en cada caso.

Editores de geometras

ST_Rotate

Rota una geometra el nmero de grados que se le especifique. Tiene la peculiaridad de que una rotacin puede realizarse desde cualquier punto, por lo que tenemos que especificarle dnde, o lo har por defecto enel 0,0.

geometryST_Rotate(geometry geomA, float rotRadians, geometry pointOrigin);

Podemos usar cualquier otra funcin de Postgis para obtener el eje de rotacin deseado, por ejemplo el propio centroide de la geometra que vamos a rotar.

ST_SetSRID

ST_Transform

ST_SetSRID estable el SRID de la geometra, pero slo a efectos de la consulta, no realiza una transformacin real del SRID de la geometra. Sirve para aquellas operaciones en que es requisito que la geometra tenga un SRID asignado, siempre y cuando estemos seguro de que el SRID que especificamos es el correcto.

Para realizar la transformacin de manera que la geometra devuelta por la funcin tenga todas sus coordenadas convertidas al SRID especificado, tenemos que usar ST_Transform:

geometryST_Transform(geometry g1, integer srid);

El SRID destino debe existir en la tabla SPATIAL_REF_SYS, y adems el Postgis que estemos usando debe estar compilado con soporte para Proj. Puede averiguarse mediante una consulta a PostGIS_Full_Version().

Porejemplo, vamos a obtener las coordenadas de un elemento en su SRID original y en otro SRID distinto. As, para obtener las coordenadas del municipio de Sevilla, sabiendo que el SRID de su geometra en la BD es 23030:

SELECT ST_AsText(geom) from municipios WHERE municipio like 'Sevilla';

Nos devuelve:

MULTIPOLYGON(((231406.703083413 4132783.99988467,231313.500105841 4132720.9999916,231252.703172508 4132809.99992668....

Y si lanzamos la misma consulta pero transformando previamente la geometra a SRID4326:

SELECT ST_AsText(ST_Transform(geom, '4326')) from municipios WHERE municipio like 'Sevilla';

Nos devuelve:

MULTIPOLYGON(((-6.03144377564774 37.3010680262285,-6.03247116367393 37.3004740219002,-6.03318839837998 37.3012575568891,...

Operadores y relaciones espaciales

&& devuelve cierto si los envelopes de las dos geometras implicadas en el predicado intersectan.

Por ejemplo, la siguiente sentencia devuelve todos aquellos municipios cuyos envelopes intersectan entre s:

SELECT a.municipio,b.municipio from municipios a, municipios b where a.gid!=b.gid and a.geom && b.geom

La versin&&&tiene el mismo funcionamiento pero para un modelo 3D

@ Devuelve verdadero si el envelope de la geometria g1 est contenido en el de la geometra g2.

Devuelve la distancia entre las dos geometras especificadas. Si no son de tipo puntual, hace un clculo previo de centroide. Por ejemplo, por ejemplo la siguiente consulta devuelve la distancia que hay entre el centroide de todos los muncipios:

SELECT a.municipio, b.municipio, (a.geom b.geom) as distancia from municipios a, municipios b

ST_Centroid

Devuelve el centroide de la geometra. Segn el tipo de geometra, y la forma de la misma, el centroide puede estar contenida o no en ella.

Centroides de multipoint, linestring, polygon y geometry collection

Volviendo al caso mencionado anteriormente de la funcin ST_Rotate, donde haba que especificarle el eje de rotacin, podramos por ejemplo combinarla con la funcin ST_Centroid para que la geometra gire sobre s misma. Por ejemplo, la siguiente consulta, ejecutada en el mdulo Postgis Viewer sobre la capa de municipios:SELECT ST_Rotate(geom, pi(), ST_Centroid(geom)) as geom, gid from municipios WHERE gid=12

Gira el municipio sobre s mismo:

Municipio rotado sobre su centroide

ST_Contains

Devuelve cierto si y slo si ningn punto de B se encuentra fuera de A y al menos un punto del interior de B se encuentra dentro de A.

booleanST_Contains(geometry geomA, geometry geomB);

Es importante la ltima condicin de la definicin, ya quesi imaginamos un LINESTRINGque siguiera el borde de un polgono, no cumplira dicha condicin, y por lo tanto, no estara contenida dentro de B.

Un polgono se contendra a s mismo?

ST_Within

Sera la inversa de la anterior. Devuelve cierto cuando la geometra A se encuentra completamente dentro de B:

booleanST_Within(geometryA, geometry B);

Busquemos por ejemplo los puntos kilomtricos contenidos en el municipio de Sevilla:

SELECT pk.* FROM municipios m, puntos_kilometricos pk WHERE m.municipio like 'Sevilla' AND ST_Within(pk.geom, m.geom)

Puntos kilomtricos dentro y fuera del municipio

ST_Covers

Esta funcin aparece para cubrir el caso de uso que quedaba hurfano con el predicado ST_CONTAINS:

booleanST_Covers(geometry A, geometry B);

En este caso, se devuelve cierto si no hay ningn punto de B fuera de la geometra A.Por lo tanto, un LINESTRING que estuviera en el borde de un POLYGON estara cubierto por elmismo.

ST_Equals

Es cierta si y slo si las geometras son las mismas, desde un punto de vista espacial, e independientemente del orden de los vrtices.

booleanST_Equals(geometry A, geometry B);

Es equivalente a: ST_COVERS(A,B) AND ST_COVERS(B,A).

Esto significa que por ejemplo, dos geometrasno tienen por qu tener el mismo nmero de vrtices para ser iguales, siempre y cuando definan la misma estructura espacial.Por ejemplo:

SELECT ST_Equals(ST_GeomFromText('LINESTRING(0 0, 10 10)'),
ST_GeomFromText('LINESTRING(0 0, 5 5, 7 7, 10 10)'));

Devuelve cierto.

ST_Intersects

Devuelve cierto siempre que las geometras intersecten. Estar contenidas, tocarse o estar superpuestas, implican interseccin.

booleanST_Intersects(geometry geomA, geometry geomB);

La siguiente consulta nos devuelve todos los municipios por los que pasa la carretera A-4:

SELECT m.* FROM carreteras c, municipios m WHERE c.matricula='A-4'AND (ST_INTERSECTS(m.geom, c.geom))

La carretera A-4 intersecta con municipios de Sevilla

Podramos aplicar en este caso la funcin ST_CONTAINS en vez de ST_INTERSECTS?

La funcin espacial inversa esST_Disjoint, que devuelve cierto slo si las geometras nointersectan.

ST_Crosses

Dos geometras se cruzan si tienen algunos puntos interiores comunes , pero no todos. Y adems,la geometra comn debe ser de una dimensionalidad espacial menor que la mxima dimensin de las geometras iniciales.

booleanST_Crosses(geometry g1, geometry g2);

La dimensin de una geometra (ST_Dimension) est definida como sigue: 0 para POINT, 1 para LINESTRING, 2 para POLYGON, y la dimensin mayor de entre los componentes que incluya una GEOMETRYCOLLECTION. Siempre ser menor o igual que la dimensin de las coordenadas que forman la geometra (ST_NDims), que puede valer 2 (x,y),3 (x,y,z) o 4 (x,y,z,m) en Postgis.

Esto significa que dos LINESTRING pueden cruzarse en un punto, ya que el POINT resultante es de dimensinmenor. Pero dos POLYGON con una misma dimensin espacial y con superficie superpuesta, no se cruzan, ya que la interseccin de ambos tiene la misma dimensin espacial que ellos.Si sabemos por ejemplo que la carretera A-4 (LINESTRING) atraviesa el municipio de Carmona (POLYGON) puede decirse que se crucen?

SELECT ST_CROSSES(m.geom, c.geom) FROM carreteras c, municipios m WHERE c.matricula='A-4' AND m.municipio like 'Carmona'

ST_Overlaps

Devuelve cierto si las geometras A y B,con la misma dimensin,comparten espacio pero no est ninguna completamente incluida en la otra.

booleanST_Overlaps(geometry A, geometry B);

Debido a lo anterior, vemos que por ejemplo un POINT y un LINESTRING, aunque el primero estuviera incluido dentro del segundo, no devolveran nunca cierto ante un predicado ST_OVERLAPS.

ST_Touches

Devuelve cierto si las geometras tienen al menos un punto en comn, pero sus interiores no intersectan.

booleanST_Touches(geometry g1, geometry g2);

No puede aplicarse sobre dos POINT, pero s sobre cualquier otra combinacin de tipos de geometras. Bsicamente, es cierto que dos geometras se tocan cuando los puntos que tienen en comn son un subconjunto de los puntos que componen sus lmites.

Procesamiento de geometras

ST_Buffer

Genera una geometra en la que todos los puntos se encuentran a una distancia igual o menor al valor del buffer de la geometra original, segn el sistema de referencia usado.

geometryST_Buffer(geometry g1, float radius_of_buffer, text buffer_style_parameters);

En el caso de polgonos, puede usarse un buffer negativo, que reducira el polgono en vez de ampliarlo.

Con esta funcin podemos responder a cuestiones como averiguar qu pozos se encuentran a una distancia mxima de la ribera de un ro, o cul es el rea de cuarentena de aquellos puntos que se consideren focos de una infeccin.

Aunque el principal uso de esta funcin es para el clculo espacial, tambin puede servirnos para crear diferencias visuales entre elementos que cumplan un determinadocriterio. Por ejemplo, supongamos que queremos que las carreteras con atributo grosor 1 (las ms importantes) se diferencien visualmente de las dems:

SELECT ST_Buffer(c.geom,200, 'endcap=square join=round') as geom, gid FROM carreteras as c WHERE c.grosor=1

Carreteras principalesLos valores de endcap, que marcan cmo tratar los puntos inicial y final de la lnea, pueden ser round (redondeado), square (plano) o flat (plano y tangente al punto). Los de join, que marcan cmo representar los ngulos, round (curvo) , mitre (puntiagudo) o bevel (tangente al punto a la distancia marcada por el buffer).

ST_Difference

Devuelve una geometra formada por la parte de A que no intersecta con B:

geometryST_Difference(geometry geomA, geometry geomB);

ST_Intersection

Devuelve una geometra formada por el espacio que comparten las geometras iniciales. Si las geometras no comparten ningn espacio, se devuelve una geometry collection vaca.

geometryST_Intersection(geometry geomA, geometry geomB);

ST_Union

Devuelve una geometra que contiene todos los puntos de las gemetras que se unen:

geometryST_Union(geometry g1, geometry g2);

b) USO DE SQL

Las sentencias SQL pueden ejecutarse directamente contra el SGBD, generalmente a travs de lnea de comandos o de programas de gestin del SGBD creados para ellos (TOAD, PgAdmin III, etc.). En esos casos, las instrucciones son las propias sentencias y los resultados consisten en los registros de salida correspondientes. Podemos hablar entonces de una interaccin directa usuario/SGBD.

Sin embargo, no es la nica manera de interaccionar con los datos. Por lo general, un usuario final lo har a travs de una tercera aplicacin creada usando un lenguaje de programacin especfico (Java, php, etc.) que se comunica con el SGBD mediante laslibrerascorrespondientes. Por ejemplo, el siguiente cdigo ejecuta una sentencia SELECT mediante una serie de objetos creados para la comunicacin con el SGBD:

import java.sql.*;...Connection conn =DriverManager.getConnection(...);Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("SELECT name FROM Customers WHERE Snum = 2001");

De esta manera, una vez obtenidos los resultados, puede hacerse con ellos cualquier cosa que el lenguaje de programacin permita: generacin de informes, presentacin de los resultados en formatos concretos, procesamiento de los datos, etc.

Hay que tener cuidado sin embargo ya que esto puede crear una dependencia con el SGBD subyaciente en caso de quese usen funcionalidades o atribuciones propias de dicho sistema, ya que el cdigo no funcinara por lo tanto contra otro SGBD. Esto puede asumirse si el Sistema que se est construyendo tiene una arquitectura tecnolgica concreta.

Si por el contrario queremos que el software generado funcine independientemente del SGBD espacial subyaciente, existen opciones como delegar la interaccin con el SGBD a una capa intermedia como un motor de persistencia. Dicho motor de persistencia debera por supuesto contarcon la capacidad de tratar los tipos espaciales de datos. Un ejemplo de esto es el conocido Hibernate Spatial.

Existe a su vez una alternativa al uso de sentencias SQL para disponer de funcionalidad espacial. Consiste bsicamente en tener una librera defunciones espaciales programadas en el lenguaje de programacin concreto que estemos usando, y, una vez generados los objetos (desde cero en el propio lenguaje o leyndolos del SGBD mediante el driver adecuado), manipularlos con las mismas.

Es el caso dela conocida librera Geotools, para el lenguaje de programacin Java. Un ejemplo simplificado de uso donde se genera un buffer de un objeto tipo Punto:

Coordinate coordenada = new Coordinate(1,1);Point punto = geometryFactory.createPoint(coordenada);Polygon poligono = punto.buffer(1000);

La ejecucin de consultas SQL contra el SGBD se limitara nicamente a las sentencias de lectura, escritura y actualizacin (INSERT, DELETE y UPDATE) de las geometras ya procesadas.

Este modo de proceder es generalmente el utilizado en los clientes SIG de escritorio. Dichos clientes soportan por lo general acceso a los distintos SGBD espaciales existentes, pero al limitar la interaccin con los mismos a las operaciones de lectura, borrado y actualizacin, y llevar a cabo las operaciones espaciales con geometras en su lenguaje de programacin, minimizan el esfuerzo que tendran que realizar a la hora de gestionar los distintos operadores y funciones espaciales de cada SGBD, que aunque implementen las mismas funcionalidades, tienen sus particularidades.

Bases de datos geogrficasA.Zabala F.Maashttp://www.lookingformaps.com/curso-postgisde Bases de datos geogrficasA.Zabala F.Maashttp://www.lookingformaps.com/curso-postgisde