3 votos

¿Comprobar si un polígono contiene múltiples geometrías de puntos utilizando PostGIS?

No se trata de un duplicado de la sección " Contar puntos en un polígono con Postgis ", ya que en el ST_Contains(geometry geomA, geometry geomB), este caso tiene dos geometrías (start_geom y end_geom) en geomB, mientras que la otra pregunta es sobre una sola geometría.

Tabla de polígonos de entrada us_county:

Column  |            Type             |                        Modifiers                        
----------+-----------------------------+--------------------------------
 gid      | integer                     | not null default nextval('us_county_gid_seq'::regclass)
 statefp  | character varying(2)        | | 
 geoid    | character varying(5)        | 
 name     | character varying(100)      | 
 geom     | geometry(MultiPolygon,4269) |

Viajes de la tabla de puntos de entrada:

Column    |         Type         |                      Modifiers                      
--------------+----------------------+-----------------------------------
 id           | integer              | 
 gid          | integer              | not null default nextval('trips_gid_seq'::regclass)
 start_geom  | geometry(Point,4326) | 
 end_geom    | geometry(Point,4326) | 

Quiero utilizar para comprobar si un polígono en us_county podría contener tanto start_geom y end_geom de un viaje puntos.

He probado las siguientes consultas:

1. esta consulta devuelve un resultado vacío, lo que no es correcto

select us_county.name, count(trips.gid) 

from trips, us_county

where st_contains(us_county.geom, trips.start_geom) and 
      st_contains(us_county.geom, trips.end_geom)

group by us_county.name;

2. una segunda idea es utilizar la función ST_Collect():

select us_county.name, count(trips.gid) 

from trips, us_county 

where st_contains(ST_Transform(us_county.geom, 4326),  
ST_Collect(trips.start_geom, trips.end_geom))

Group by us_county.name;

Pero esto resulta ser muy lento, para 3k polígonos y 50k puntos, la consulta se ejecuta más de 40min.

2voto

Chris Puntos 128

Parece que su principal problema son los diferentes sistemas de proyección utilizados. Debería poder volver a proyectar sobre la marcha para completar la consulta utilizando ST_Transform:

select us_county.name, count(trips.gid) 
from trips, us_county
where st_contains(ST_Transform(us_county.geom,4326), trips.start_geom) and 
      st_contains(ST_Transform(us_county.geom,4326), trips.end_geom)
group by us_county.name;

2voto

MBCook Puntos 8316

Puedes combinar los puntos con ST_Collect :

SELECT us_county.name, count(trips.gid) 
FROM trips, us_county
WHERE ST_Contains(us_county.geom, 
                  ST_Collect(trips.start_geom, trips.end_geom))
GROUP BY us_county.name;

2voto

gommo Puntos 697

Una forma de conseguir que esto funcione y acelerar la consulta sería "etiquetar por regiones" las geometrías de la tabla de puntos primero. Esto sería algo así:

ALTER TABLE trips
ADD COLUMN start_county_id char(5) -- assuming this is a fips code
ADD COLUMN end_county_id char(5);

UPDATE trips
SET start_county_id = a.geoid
FROM us_county AS a
WHERE ST_Intersects(trips.start_geom, a.geom);

UPDATE trips
SET end_county_id = a.geoid
FROM us_county AS a
WHERE ST_Intersects(trips.end_geom, a.geom);

Las actualizaciones serán costosas, pero esto es a menudo aceptable ya que sólo tiene que ocurrir una vez. A continuación, lo único que hay que hacer es cotejar los identificadores de condado de inicio y fin con el código fips del condado. Puedes poner un índice en las columnas start_county_id y end_county_id, y la consulta debería ser mucho más rápida. Algo así como:

SELECT a.geoid, c.cnt
FROM us_counties AS a,
     (SELECT b.start_county_id, b.end_county_id, COUNT(b.id) as cnt
     FROM trips as b
     WHERE b.start_count_id = b.end_county_id
     GROUP BY b.start_county_id) as c
WHERE a.geoid = b.start_county_id

Las consultas espaciales son, por naturaleza, caras. Tengo una tabla de puntos con más de 20 millones de filas y una tabla de polígonos con 75.000, y esta técnica reduce las consultas (muy similares a las tuyas) a unos pocos segundos.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X