20. Funciones de Construcción de Geometrías¶
Todas las funciones que hemos visto hasta ahora trabajan con geometrías «tal cual» y devuelven
análisis de los objetos (:command:ST_Length(geometry), :command:ST_Area(geometry)),
serializaciones de los objetos (:command:ST_AsText(geometry), :command:ST_AsGML(geometry)),
partes del objeto (:command:ST_RingN(geometry,n)) o
pruebas verdadero/falso (:command:ST_Contains(geometry,geometry), :command:ST_Intersects(geometry,geometry)).
Las «funciones de construcción de geometrías» toman geometrías como entrada y generan nuevas formas.
20.1. ST_Centroid / ST_PointOnSurface¶
Una necesidad común al componer una consulta espacial es reemplazar un polígono con una representación puntual de la entidad. Esto es útil para las uniones espaciales (como se discute en :ref:polypolyjoins) porque usar :command:ST_Intersects(geometry,geometry) sobre dos capas de polígonos a menudo resulta en doble conteo: un polígono en un límite intersectará un objeto a ambos lados; reemplazarlo con un punto obliga a que esté en un lado u otro, no en ambos.
:command:ST_Centroid(geometry) devuelve un punto que está aproximadamente en el centro de masa del argumento de entrada. Este cálculo simple es muy rápido, pero a veces no es deseable, porque el punto devuelto no necesariamente se encuentra dentro de la propia geometría. Si la entidad de entrada tiene una concavidad (imagine la letra “C”), el centroide devuelto podría no estar en el interior de la entidad.
:command:ST_PointOnSurface(geometry) devuelve un punto que está garantizado dentro del argumento de entrada. Esto lo hace más útil para calcular «puntos representativos» en junturas (joins) espaciales.

-- Compare the location of centroid and point-on-surface for a concave geometry
SELECT ST_Intersects(geom, ST_Centroid(geom)) AS centroid_inside,
ST_Intersects(geom, ST_PointOnSurface(geom)) AS pos_inside
FROM (VALUES
('POLYGON ((30 0, 30 10, 10 10, 10 40, 30 40, 30 50, 0 50, 0 0, 0 0, 30 0))'::geometry)
) AS t(geom);
centroid_inside | pos_inside
-----------------+------------
f | t
20.2. ST_Buffer¶
La operación de buffer es común en los flujos de trabajo SIG, y también está disponible en PostGIS. :command:ST_Buffer(geometry,distance) recibe una distancia de buffer y una geometría, y devuelve un polígono con un límite a la distancia especificada de la geometría de entrada.

Por ejemplo, si el Servicio de Parques de EE. UU. quisiera establecer una zona de tráfico marítimo alrededor de Liberty Island, podría construir un polígono de buffer de 500 metros alrededor de la isla. Liberty Island es un solo bloque censal en nuestra tabla nyc_census_blocks, por lo que podemos extraerlo y generar el buffer fácilmente.
-- Make a new table with a Liberty Island 500m buffer zone
CREATE TABLE liberty_island_zone AS
SELECT ST_Buffer(geom,500)::geometry(Polygon,26918) AS geom
FROM nyc_census_blocks
WHERE blkid = '360610001001001';

La función :command:ST_Buffer también acepta distancias negativas y construye polígonos inscritos dentro de las geometrías poligonales de entrada. Para líneas y puntos simplemente devolverá un resultado vacío.

20.3. ST_Intersection¶
Otra operación clásica de SIG —el «overlay» o superposición— crea una nueva cobertura al calcular la intersección de dos polígonos superpuestos. El resultado tiene la propiedad de que cualquier polígono de los padres puede construirse a partir de la unión de polígonos en el resultado.
La función :command:ST_Intersection(geometry A, geometry B) devuelve el área espacial (o línea, o punto) que ambos argumentos tienen en común. Si los argumentos no se intersectan, la función devuelve una geometría vacía.
-- What is the area these two circles have in common?
-- Using ST_Buffer to make the circles!
SELECT ST_AsText(ST_Intersection(
ST_Buffer('POINT(0 0)', 2),
ST_Buffer('POINT(3 0)', 2)
));

20.4. ST_Union¶
En el ejemplo anterior intersectamos geometrías, creando una nueva geometría que tenía líneas de ambas entradas. La función :command:ST_Union hace lo contrario: toma las entradas y elimina las líneas comunes. Existen dos formas de la función :command:ST_Union:
ST_Union(geometry, geometry): A two-argument version that takes in two geometries and returns the merged union. For example, our two-circle example from the previous section looks like this when you replace the intersection with a union.
-- What is the total area these two circles cover? -- Using ST_Buffer to make the circles! SELECT ST_AsText(ST_Union( ST_Buffer('POINT(0 0)', 2), ST_Buffer('POINT(3 0)', 2) ));
ST_Union([geometry]): An aggregate version that takes in a set of geometries and returns the merged geometry for the entire group. The aggregate ST_Union can be used with the
GROUP BY
SQL statement to create carefully merged subsets of basic geometries. It is very powerful.
Como ejemplo de agregación con :command:ST_Union, consideremos nuestra tabla nyc_census_blocks. La geografía censal está cuidadosamente construida de modo que las geografías más grandes puedan generarse a partir de las más pequeñas. Así, podemos crear un mapa de tramos censales uniendo los bloques que forman cada tramo. O podemos crear un mapa de condados uniendo los bloques que caen dentro de cada condado.
Para llevar a cabo la unión, obsérvese que la clave única blkid en realidad incorpora información sobre las geografías de nivel superior. Aquí están las partes de la clave para Liberty Island que usamos anteriormente:
360610001001001 = 36 061 000100 1 001
36 = State of New York
061 = New York County (Manhattan)
000100 = Census Tract
1 = Census Block Group
001 = Census Block
Así, podemos crear un mapa de condados uniendo todas las geometrías que comparten los mismos primeros 5 dígitos de su blkid. Sea paciente; esto es computacionalmente costoso y puede tardar uno o dos minutos.
-- Create a nyc_census_counties table by merging census blocks
CREATE TABLE nyc_census_counties AS
SELECT
ST_Union(geom)::Geometry(MultiPolygon,26918) AS geom,
SubStr(blkid,1,5) AS countyid
FROM nyc_census_blocks
GROUP BY countyid;

Una prueba de área puede confirmar que nuestra operación de unión no perdió ninguna geometría. Primero, calculamos el área de cada bloque censal individual y sumamos esas áreas agrupando por id de condado censal.
SELECT SubStr(blkid,1,5) AS countyid, Sum(ST_Area(geom)) AS area
FROM nyc_census_blocks
GROUP BY countyid
ORDER BY countyid;
countyid | area
----------+------------------
36005 | 110196022.906506
36047 | 181927497.678368
36061 | 59091860.6261323
36081 | 283194473.613692
36085 | 150758328.111199
Luego calculamos el área de cada uno de nuestros nuevos polígonos de condado a partir de la tabla de condados:
SELECT countyid, ST_Area(geom) AS area
FROM nyc_census_counties
ORDER BY countyid;
countyid | area
----------+------------------
36005 | 110196022.906507
36047 | 181927497.678367
36061 | 59091860.6261324
36081 | 283194473.593646
36085 | 150758328.111199
¡La misma respuesta! Hemos construido exitosamente una tabla de condados de NYC a partir de nuestros datos de bloques censales.
20.5. Lista de funciones¶
ST_Centroid(geometry) <http://postgis.net/docs/ST_Centroid.html>_: Devuelve una geometría de punto que representa el centro de masa de la geometría de entrada.
ST_PointOnSurface(geometry) <http://postgis.net/docs/ST_PointOnSurface.html>_: Devuelve una geometría de punto que está garantizada en el interior de la geometría de entrada.
ST_Buffer(geometry, distance) <http://postgis.net/docs/ST_Buffer.html>_: Para geometría: devuelve una geometría que representa todos los puntos cuya distancia desde esta geometría es menor o igual a la distancia. Los cálculos se realizan en el sistema de referencia espacial de esta geometría. Para geografía: usa un envoltorio de transformación planar.
ST_Intersection(geometry A, geometry B) <http://postgis.net/docs/ST_Intersection.html>_: Devuelve una geometría que representa la porción compartida de geomA y geomB. La implementación en geografía realiza una transformación a geometría para efectuar la intersección y luego transforma de nuevo a WGS84.
ST_Union() <http://postgis.net/docs/ST_Union.html>_: Devuelve una geometría que representa la unión de conjuntos de puntos de las geometrías.
ST_AsText(text) <http://postgis.net/docs/ST_AsText.html>_: Devuelve la representación Well-Known Text (WKT) de la geometría/geografía sin metadatos de SRID.
substring(string [from int] [for int]) <http://www.postgresql.org/docs/current/static/functions-string.html>_: Función de PostgreSQL para extraer una subcadena que coincide con una expresión regular SQL.
sum(expresión): Función de PostgreSQL que devuelve la suma de los valores de un conjunto de registros.