Agregar columna de geometría adicional en PostGIS?

10

Estoy importando muchos conjuntos de geodatos en PostGIS, y tienen diferentes SRID's. (Algunos tienen EPSG:3857, algunos EPSG:4326, algo más).

Me gustaría crear un adicional geometry column, por ejemplo. the_geom_mercatorcon SRID EPSG:3857, y también mantenga la geomcolumna original en lo SRIDque sea que venga

¿Cómo puedo hacer esto con una función PostGIS?

Knutole
fuente

Respuestas:

18

Para agregar una columna a una tabla existente, use ALTER TABLE DDL , por ejemplo:

ALTER TABLE my_table
  ADD COLUMN the_geom_mercator
    geometry(Geometry,3857);

que se puede completar desde otra columna (the_geom) usando:

UPDATE my_table SET
  the_geom_mercator = ST_Transform(the_geom, 3857)
FROM spatial_ref_sys
WHERE ST_SRID(the_geom) = srid;

(la tercera línea FROM spatial_ref_sys ...no es necesaria, pero protege los intentos de transformación con proyecciones desconocidas o inválidas, lo que genera errores).

Y si esta tabla se va a mantener (agregar / actualizar), puede usar una función de activación para actualizar the_geom_mercator, por ejemplo:

CREATE OR REPLACE FUNCTION my_table_tg_fn() RETURNS trigger AS
$BODY$BEGIN
  IF TG_OP = 'INSERT' AND NEW.the_geom ISNULL THEN
    RETURN NEW; -- no new geometry
  ELSIF TG_OP = 'UPDATE' THEN
    IF NEW.the_geom IS NOT DISTINCT FROM OLD.the_geom THEN
      RETURN NEW; -- same old geometry
    END IF;
  END IF;
  -- Attempt to transform a geometry
  BEGIN
    NEW.the_geom_mercator := ST_Transform(NEW.the_geom, 3857);
  EXCEPTION WHEN SQLSTATE 'XX000' THEN
    RAISE WARNING 'the_geom_mercator not updated: %', SQLERRM;
  END;
  RETURN NEW;
END;$BODY$ LANGUAGE plpgsql;

CREATE TRIGGER my_table_tg BEFORE INSERT OR UPDATE
   ON my_table FOR EACH ROW
   EXECUTE PROCEDURE my_table_tg_fn();

Tenga en cuenta que ST_Transform debe atrapar errores y mostrar una advertencia, por ejemplo:

postgis=# INSERT INTO my_table(the_geom)
postgis-# VALUES (ST_SetSRID(ST_MakePoint(0,1), 123))
postgis-# RETURNING the_geom, the_geom_mercator;
WARNING:  the_geom_mercator not updated: GetProj4StringSPI: Cannot find SRID (123) in spatial_ref_sys
-[ RECORD 1 ]-----+---------------------------------------------------
the_geom          | 01010000207B0000000000000000000000000000000000F03F
the_geom_mercator |

INSERT 0 1
Mike T
fuente
Gracias por una gran respuesta. Es realmente bueno usar disparadores, comenzaré a hacerlo. ¿Podría agregar ese disparador a la base de datos en su lugar, para no tener que agregar este disparador para cada nueva tabla?
knutole
Estoy agregando datos a postgis con shp2psqly la tabla se crea cuando se canaliza psql. ¿Entonces realmente no puedo agregar un disparador antes de que exista la tabla?
knutole
1
Si está utilizando shp2pgsql, use una declaración de actualización, consulte más arriba. Un activador es útil si necesita mantener una tabla, pero no para cargar.
Mike T
2

Primero cree una tabla normal no espacial, que ya tiene. En segundo lugar, agregue una columna espacial a la tabla utilizando la función OpenGIS "AddGeometryColumn".

Ejemplo:

CREATE TABLE terrain_points ( 
ogc_fid serial NOT NULL, 
elevation double precision,
);

SELECT AddGeometryColumn('terrain_points', 'wkb_geometry', 3725, 'POINT', 3 );
hoogw
fuente
1

Puede crear una columna de geometría SRID sin restricciones para mantener la forma nativa y luego transformarla en existente. Aquí hay un ejemplo artificial asumiendo que tiene polígonos que está copiando de una tabla de etapas (si ha mezclado, puede establecer el tipo en geometría, por ejemplo, geometría (Geometry, 3857):

CREATE TABLE poi(gid serial primary key, 
   geom_native geometry(POLYGON),  
   geom_mercator geometry(POLYGON,3857) );

INSERT INTO TABLE poi(geom_native, geom_mercator)
SELECT geom, ST_Transform(geom, 3857)
   FROM staging.imported_poly;
LR1234567
fuente
Gracias por tu respuesta. ¿Hay alguna manera de hacer esto en tablas ya existentes (es decir, sin usar tablas de preparación)? Digamos que ya tengo una tabla, con una geomcolumna, y simplemente quiero agregar otra the_geom_webmercatorcolumna. ¿Como podría hacerlo?
knutole