Introducción a PostGIS#
Introducción#
PostGIS es una extensión de PostgreSQL que incorpora funcionalidad espacial a este SABD al agregar soporte para tipos de datos espaciales, índices espaciales y funciones espaciales. Al estar construido sobre PostgreSQL, PostGIS hereda automáticamente todas sus ventajas como SABD organizacional, así como estándares abiertos para su implementación. Tanto PostgreSQL como PostGIS son proyectos de software de código abierto.
Refractions Research lanzó la primera versión de PostGIS en 2001, la cual contaba con objetos, índices y unas cuantas funciones. A través de los años, el proyecto se enriqueció con la implementación de la especificación Simple Features for SQL (SFSQL) del Open Geospatial Consortium (OGC), la cual define cómo soportar consultas espaciales en bases de datos relacionales, y con el aporte de otros proyectos de desarrollo de software apoyados por OSGeo, como la biblioteca “Geometry Engine, Open Source” (GEOS), la cual proporciona el código fuente necesario para implementar los algoritmos de SFSQL (ej. ST_Intersects()
, ST_Buffer()
, ST_Union()
) y muchos otros.
Instalación#
Las instrucciones detalladas para la instalación de PostGIS, en diferentes sistemas operativos, pueden encontrarse en Introduction to PostGIS - Installation.
Creación de bases de datos#
PostgreSQL cuenta con varias interfaces administrativas. La principal es psql, una herramienta de línea de comandos para ingresar consultas SQL. Otra interfaz popular de PostgreSQL es la herramienta gráfica gratuita y de código abierto pgAdmin. Todas las consultas realizadas en pgAdmin también se pueden hacer en la línea de comandos con psql. pgAdmin también incluye un visor de geometrías que puedes usar para visualizar espacialmente las consultas de PostGIS.
En el caso de pgAdmin, una base de datos espacial puede crearse igual que cualquier otra base de datos, con la opción de menú Databases - New Database y ejecutando además el comando:
-- Creación de la extensión PostGIS
CREATE EXTENSION postgis;
Este comando crea la extensión espacial PostGIS para una base de datos.
Para confirmar que PostGIS está correctamente instalada, puede ejecutarse una de sus funciones. Por ejemplo:
-- Consulta de la versión de PostGIS instalada
SELECT postgis_full_version();
Carga de datos#
Existen varias opciones para cargar datos espaciales en PostgreSQL-PostGIS. En las secciones siguientes se describen algunas.
Desde un archivo de respaldo#
Este método permite restaurar una base de datos a partir de su respaldo en un archivo (ej. .backup
). En pgAdmin, está disponible en la opción Restore… del menú que se despliega al hacer clic derecho en el ícono de una base de datos.
Con la herramienta ogr2ogr#
ogr2ogr es un programa que forma parte de la biblioteca Geospatial Data Abstraction Library (GDAL), la cual se enfoca en la conversión entre formatos vectoriales y raster. ogr2ogr
realiza conversiones entre formatos vectoriales (ej. SHP, GPKG, GML, KML) y se ejecuta desde la línea de comandos del sistema operativo.
Para acceder una base de datos PostgreSQL-PostGIS, ogr2ogr
requiere el nombre de la base de datos (dbname
), la computadora en la que está alojada (host
), un usuario con los derechos necesarios para cargar los datos (user
) y su clave. Para no especificar la clave en el comando (lo que sería muy inseguro), se recomienda especificarla en una variable del sistema operativo.
# Especificación de la clave de PostgreSQL como variable del sistema operativo
# mi_clave_de_postgresql debe sustituirse por la clave verdadera
set PGPASSWORD=mi_clave_de_postgresql
Por ejemplo, el siguiente comando carga una capa de provincias de Costa Rica alojada en un servicio WFS del Instituto Geográfico Nacional (IGN) en una tabla de una base de datos PostgreSQL-PostGIS.
# Carga de una capa alojada en un servicio WFS en una base de datos PostgreSQL-PostGIS
ogr2ogr ^
-makevalid ^
-nln provincias ^
-nlt PROMOTE_TO_MULTI ^
-lco GEOMETRY_NAME=geom ^
Pg:"dbname=cr host=localhost user=postgres port=5432" ^
WFS:"https://geos.snitcr.go.cr/be/IGN_5_CO/wfs" "IGN_5_CO:limiteprovincial_5k"
El siguiente comando carga un archivo CSV, con registros de presencia de félidos de Costa Rica obtenidos a través de una consulta al portal de la Infraestructura Mundial de Información en Biodiversidad (GBIF), en una tabla de una base de datos PostgreSQL-PostGIS. El archivo CSV también puede descargarse de gf0659-exploraciongeodatos/2023-ii. El resultado es una capa con geometrías de puntos, cuyas coordenadas provienen de las columnas decimalLongitude
y decimalLatitude
. Note el uso de las opciones -s_srs EPSG:4326
y -t_srs EPSG:5367
para especificar los sistemas de coordenadas de origen y destino, respectivamente.
# Carga de una capa contenida en un archivo CSV en una base de datos PostgreSQL-PostGIS
ogr2ogr ^
-nln felidos ^
-oo X_POSSIBLE_NAMES=decimalLongitude -oo Y_POSSIBLE_NAMES=decimalLatitude ^
-lco GEOMETRY_NAME=geom ^
-s_srs EPSG:4326 ^
-t_srs EPSG:5367 ^
Pg:"dbname=cr host=localhost user=postgres port=5432" ^
felidos.csv
Con la herramienta shp2pgsql#
La herramienta shp2pgsql permite cargar shapefiles como tablas en bases de datos PostgreSQL-PostGIS. Puede utilizarse desde la línea de comandos del sistema operativo o desde una interfaz gráfica.
Con QGIS#
El sistema de información geográfica de escritorio QGIS incluye varias herramientas para cargar datos en bases de datos PostgreSQL-PostGIS, como la disponible en la opción de menú Database - DB Manager - Import Layer/File…., la cual permite cargar capas físicas o virtuales disponibles en el navegador de QGIS.
Ejercicios#
Para cargar los datos requeridos para resolver estos ejercicios, puede consultar Introduction to PostGIS - Loading spatial data.
Cree una base de datos PostgreSQL-PostGIS con nombre
nyc
.Cargue en
nyc
el archivo de respaldo de la base de datos.En la base de datos
nyc
, examine:Las columnas de geometría de las tablas (ej.
geom
).La tabla
spatial_ref_sys
.Las vistas
geometry_columns
ygeography_columns
.
Lea la descripción de los datos de
nyc
en Introduction to PostGIS - About our data.En QGIS, cree una conexión a
nyc
y visualice sus tablas.Ejecute las consultas SQL en:
Cargue las siguientes capas del Sistema Nacional de Información Territorial (SNIT) como tablas de una nueva base de datos PostgreSQL-PostGIS llamada
cr
:Provincias.
Cantones.
Distritos.
Áreas de conservación.
Áreas silvestres protegidas.
Red vial 1:200 mil.
Hidrografía 1:5 mil.
Aeródromos 1: 200 mil.
De gf0659-exploraciongeodatos/2023-ii descargue el archivo
felidos.csv
y cárguelo como una tabla en la base de datoscr
.
Geometrías#
Como se mencionó en el capítulo anterior, una base de datos espacial proporciona tipos de datos geométricos para manejar datos espaciales. Con los siguientes comandos, se crea una tabla PostgreSQL-PostGIS, que incluye una columna de tipo GEOMETRY
, y se insertan geometrías de diferentes clases. Ejecute los comandos en alguna de las bases de datos creadas como parte de los ejercicios.
-- Creación de la tabla geometries
CREATE TABLE geometries (name VARCHAR, geom GEOMETRY);
-- Inserción de registros con diferentes tipos de geometrías
INSERT INTO geometries VALUES
('Point', 'POINT(0 0)'),
('Linestring', 'LINESTRING(0 0, 1 1, 2 1, 2 2)'),
('Polygon', 'POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))'),
('PolygonWithHole', 'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1))'),
('Collection', 'GEOMETRYCOLLECTION(POINT(2 0),POLYGON((0 0, 1 0, 1 1, 0 1, 0 0)))');
-- Consulta de la tabla geometries
SELECT name, ST_AsText(geom) FROM geometries;
La tabla geometries
contiene cinco geometrías: un punto, una línea, un polígono, un polígono con un hoyo y una colección.
Tablas y vistas de metadatos#
De acuerdo con la especificación SFSQL, PostGIS proporciona, en cada base de datos, varias tablas y vistas con metadatos sobre las columnas de geometrías:
spatial_ref_sys
es una tabla que define los sistemas de referencia espaciales (SRS) (también llamados sistemas de referencia de coordenadas o CRS) que pueden emplearse en cada base de datos PostGIS.geometry_columns
es una vista que contiene un registro por cada columna de tipoGEOMETRY
que ha sido definida en la base de datos.
Tipos de geometrías#
La especificación SFSQL define la representación de objetos espaciales de dos dimensiones. Otras especificaciones y aportes de diferentes SABD permiten representar geometrías de más dimensiones.
Existen varias funciones que permiten obtener información general sobre objetos espaciales:
ST_GeometryType(geometry) retorna el tipo de la geometría.
ST_NDims(geometry) retorna la cantidad de dimensiones de la geometría.
ST_SRID(geometry) retorna el identificador del SRS de la geometría.
-- Información general sobre objetos de la tabla geometries
SELECT name, ST_GeometryType(geom), ST_NDims(geom), ST_SRID(geom)
FROM geometries;
name | st_geometrytype | st_ndims | st_srid
-----------------+-----------------------+----------+---------
Point | ST_Point | 2 | 0
Polygon | ST_Polygon | 2 | 0
PolygonWithHole | ST_Polygon | 2 | 0
Collection | ST_GeometryCollection | 2 | 0
Linestring | ST_LineString | 2 | 0
Ejercicio:
Con las mismas funciones del ejemplo anterior, obtenga información general sobre las geometrías de las tablas de nyc
y cr
.
Puntos#
Un punto espacial representa una ubicación indivisible. Se representa con una sola coordenada (incluyendo ya sea 2, 3 o 4 dimensiones). Los puntos se utilizan para representar objetos cuando los detalles exactos, como la forma y el tamaño, no son importantes en la escala que se utiliza. Por ejemplo, las ciudades en un mapa del mundo pueden describirse como puntos, mientras que un mapa de una provincia podría representar las ciudades como polígonos.
-- Representación de una geometría de punto en el formato Well-Known Text (WKT)
SELECT ST_AsText(geom)
FROM geometries
WHERE name = 'Point';
POINT(0 0)
-- Representación de una geometría de punto en el formato Geography Markup Language (GML)
SELECT ST_AsGML(geom)
FROM geometries
WHERE name = 'Point';
<gml:Point><gml:coordinates>0,0</gml:coordinates></gml:Point>
-- Representación de una geometría de punto en el formato Keyhole Markup Language (KML)
-- (parece requerir que la geometría tenga asignado un SRS)
SELECT ST_AsKML(geom)
FROM felidos
LIMIT 1;
<Point><coordinates>-83.53046900000354,10.595039999999209</coordinates></Point>
-- Representación de una geometría de punto en el formato GeoJSON
SELECT ST_AsGeoJSON(geom)
FROM geometries
WHERE name = 'Point';
{"type":"Point","coordinates":[0,0]}
Algunas funciones para trabajar con puntos son:
ST_X(geometry): retorna el valor de x.
ST_Y(geometry): retorna el valor de y.
-- Valores x e y de las coordenadas de los registros de presencia de pumas
SELECT species, ST_X(geom), ST_Y(geom), ST_SRID(geom)
FROM felidos
WHERE species = 'Puma concolor';
Líneas#
Una línea (linestring) es un trayecto entre ubicaciones. Toma la forma de una serie ordenada de dos o más puntos. Objetos como carreteras y ríos suelen representarse como líneas. Se dice que una línea es cerrada si comienza y termina en el mismo punto. Se dice que es simple si no se cruza ni se toca a sí misma (excepto en sus extremos, si está cerrada). Una misma línea puede ser cerrada y simple.
Algunas funciones para trabajar con líneas son:
ST_Length(geometry): retorna la longitud de la línea.
ST_StartPoint(geometry): retorna el punto inicial de la línea, como un objeto tipo
POINT
.ST_EndPoint(geometry): retorna el punto final de la línea, como un objeto tipo
POINT
.ST_NPoints(geometry): retorna el número de puntos que componen la línea.
-- Información sobre una línea
SELECT
ST_Length(geom),
ST_AsText(ST_StartPoint(geom)),
ST_AsText(ST_EndPoint(geom)),
ST_NPoints(geom)
FROM geometries
WHERE name = 'Linestring';
Polígonos#
Un polígono es una representación de un área. El límite exterior del polígono está representado por un anillo. Este anillo es una línea que es tanto cerrada como simple, según se definió anteriormente. Los huecos dentro del polígono también están representados por anillos.
Los polígonos se utilizan para representar objetos cuyo tamaño y forma son importantes. Los límites de una ciudad, parques, planos de edificios o cuerpos de agua son comúnmente representados como polígonos cuando la escala es suficientemente detallada para ver su área. Las carreteras y ríos a veces pueden ser representados como polígonos.
La siguiente consulta SQL retorna las geometrías asociadas a polígonos en la tabla geometries
.
-- Geometrías de polígonos
SELECT ST_AsText(geom)
FROM geometries
WHERE name LIKE 'Polygon%';
Algunas funciones para trabajar con polígonos son:
ST_Area(geometry): retorna el área de un polígono.
ST_NRings(geometry): retorna el número de anillos de un polígono.
ST_ExteriorRing(geometry): retorna el anillo exterior de un polígono como un objeto
LINESTRING
.ST_InteriorRingN(geometry,n): retorna un anillo interior de un polígono, especificado por
n
, como un objetoLINESTRING
.ST_Perimeter(geometry): retorna la longitud de todos los anillos.
-- Área y perímetro de la provincia de San José
SELECT
provincia,
ROUND(ST_Area(geom)::numeric, 2) / 10^6 AS area_km2,
ROUND(ST_Perimeter(geom)::numeric, 2) / 10^3 AS perimetro_km
FROM provincias
WHERE provincia = 'San José';
Ejercicios:
Calcule el área de todas las provincias mediante
ST_Area()
y compárela con el valor de la columnaÁrea
.Calcula la suma de las áreas de las provincias y compárela con la suma de la columna
Área
.
Colecciones#
Hay cuatro tipos de colecciones, los cuales agrupan geometrías en conjuntos.
MultiPoint
: colección de puntos.MultiLineString
: colección de líneas.MultiPolygon
: colección de polígonos.GeometryCollection
: colección heterogénea de cualquier tipo de geometrías (incluyendo otras colecciones).
La siguiente consulta SQL retorna las geometrías asociadas a una colección.
-- Geometrías de colecciones
SELECT ST_AsText(geom)
FROM geometries
WHERE name = 'Collection';
GEOMETRYCOLLECTION(POINT(2 0),POLYGON((0 0, 1 0, 1 1, 0 1, 0 0)))
Algunas funciones para trabajar con colecciones son:
ST_NumGeometries(geometry): retorna el número de partes de una colección.
ST_GeometryN(geometry,n): retorna una parte de una colección.
ST_Area(geometry): retorna el área total de todas las partes que son polígonos.
ST_Length(geometry): retorna la longitud total de todas las partes que son líneas.
Relaciones topológicas#
Las relaciones topológicas, también llamadas relaciones topológicas binarias, son expresiones lógicas (verdaderas o falsas) sobre las relaciones espaciales entre dos objetos. Por ejemplo, si a
y b
son dos objetos espaciales (ej. puntos, líneas, polígonos), se pueden considerar relaciones topológicas como las siguientes:
a
interseca ab
a
es adyacente ab
a
está dentro deb
b
está contenido ena
Las relaciones topológicas están estandarizadas en el modelo Dimensionally Extended 9-Intersection Model (DE-9IM).
La especificación SFSQL define varias funciones para relaciones espaciales, las cuales se explican en las secciones subsiguientes.
ST_Equals()
#
ST_Equals(geometry A, geometry B) retorna TRUE
si geometry A
y geometry B
son espacialmente iguales.
-- Selección de una geometría
SELECT name, geom
FROM nyc_subway_stations
WHERE name = 'Broad St';
name | geom
----------+---------------------------------------------------
Broad St | 0101000020266900000EEBD4CF27CF2141BC17D69516315141
-- Evaluación de la igualdad de las geometrías
SELECT name
FROM nyc_subway_stations
WHERE ST_Equals(
geom,
'0101000020266900000EEBD4CF27CF2141BC17D69516315141');
Broad St
ST_Intersects()
, ST_Disjoint()
, ST_Crosses()
, ST_Overlaps()
y ST_Touches()
#
ST_Intersects()
#
ST_Intersects(geometry A, geometry B) retorna TRUE
si geometry A
y geometry B
comparten espacio en sus bordes o en sus interiores.
ST_Disjoint()
#
ST_Disjoint(geometry A, geometry B) retorna TRUE
si geometry A
y geometry B
no comparten espacio en sus bordes o en sus interiores. Es la función opuesta a ST_Intersects()
. De hecho, es más eficiente usar la expresión NOT (ST_Intersects(geometry A, geometry B))
que ST_Disjoint(geometry A, geometry B)
debido a que las intersecciones pueden comprobarse mediante índices, mientras que las disjunciones no.
ST_Crosses()
#
Para comparaciones de multipunto-polígono, multipunto-línea, línea-línea, línea-polígono y línea-multipolígono, ST_Crosses(geometry A, geometry B) retorna TRUE
si la intersección resulta en una geometría cuyo número de dimensiones es menor que el número máximo de dimensiones de las dos geometrías originales y el conjunto de intersección está en el interior de ambas geometrías originales.
ST_Overlaps()
#
ST_Overlaps(geometry A, geometry B) compara dos geometrías de la misma cantidad de dimensiones y retorna TRUE
si su intersección resulta en una geometría diferente de ambas pero de la misma cantidad de dimensiones.
ST_Touches()
#
ST_Touches(geometry A, geometry B) retorna TRUE
si los límites de alguna de las geometrías se intersectan o si el interior de solo una de las geometrías intersecta el límite de la otra.
ST_Within()
y ST_Contains()
#
Tanto ST_Within()
como ST_Contains()
comprueban si una geometría está completamente dentro de la otra.
ST_Within()
#
ST_Within(geometry A, geometry B) retorna TRUE
si geometry A
está completamente dentro de geometry B
.
ST_Contains()
#
ST_Contains(geometry A, geometry B) retorna TRUE
si geometry B
está completamente contenida en geometry A
.
Relaciones de distancia#
Un problema muy común en sistemas de información geográfica es “encuentre todo lo que esté a una distancia X de estas cosas”. Las funciones ST_Distance()
y ST_DWithin()
pueden ayudar a resolver ese tipo de problemas.
ST_Distance()
y ST_DWithin()
#
ST_Distance()
#
La función ST_Distance(geometry A, geometry B) calcula la distancia más corta entre dos geometrías y la devuelve como un número de tipo float
.
-- Cálculo de la distancia entre dos objetos
SELECT ST_Distance(
ST_GeometryFromText('POINT(0 5)'),
ST_GeometryFromText('LINESTRING(-2 2, 2 2)'));
3
ST_DWithin()
#
La función ST_DWithin() permite probar si dos objetos están a una cierta distancia el uno del otro. Esto es útil para preguntas como “¿cuántos árboles están dentro de un buffer de 500 metros de la carretera?”. Con ST_DWithin()
, se puede comprobar la relación de distancia sin generar el buffer.
-- Calles a una distancia de 10 metros o menos de una estación del tren subterráneo
SELECT name
FROM nyc_streets
WHERE ST_DWithin(
geom,
ST_GeomFromText('POINT(583571 4506714)',26918),
10
);
name
--------------
Wall St
Broad St
Nassau St
Ejercicios#
Encuentre todos los registros de presencia de félidos en un radio de 10 km del punto (-84.0, 10.0) (WGS84).
Para el punto más cercano a (-84.0, 10.0), encuentre su:
Cantón
Distrito
Área de conservación
ASP
Encuentre las vías en un radio de 1 km del punto más cercano a (-84.0, 10.0).