5 votos

¿Calculando la distancia más corta entre polígonos?

Tengo muchos polígonos guardados en una mesa. Quiero filtrar los polígonos donde se separan demasiado lejos (digamos 1km).

Mi enfoque es: calcular la distancia mínima entre un polígono en particular y otros polígonos, y almacenar el valor en una nueva columna de la tabla.

Luego filtra el polígono con una distancia mínima superior a 1 km.

He tratado de usar:

ALTER TABLE "int_20190124" ADD "nearestDistance" float8;
INSERT INTO "int_20190124"("nearestDistance")
VALUES
(
SELECT ST_Distance("int_20190124".geom, "int_20190124".geom)
FROM "int_20190124"
ORDER BY ST_Distance("int_20190124".geom, "int_20190124".geom)
LIMIT 1
)

Soy muy nuevo en Postgis.

7voto

Anton8000 Puntos 165

Puede utilizar ST_ClusterDBSCAN para agrupar las geometrías cercanas y asignarles un id de cluster. El ID de clúster será nulo para las geometrías individuales que no estén a la distancia especificada de otra.

Imagen tomada de la sección de ayuda que muestra los ID de los clústeres:

enter image description here

Esta consulta debe devolver sólo los registros en un radio de 1000 m de Otro. minpoints := 2 es evitar que los puntos individuales obtengan un ID de clúster (ya que siempre están a la distancia de sí mismos):

SELECT * FROM
   (SELECT *, ST_ClusterDBSCAN(geom, eps := 1000, minpoints := 2) OVER () clusterid
      FROM int_20190124) t1
  WHERE t1.clusterid IS NOT NULL;

Ejemplo con puntos y 10000 m de distancia: enter image description here

0 votos

¿Por qué puntos mínimos := 2 y no puntos mínimos := 1?

0 votos

Con 1, los registros individuales sin otros Puntos cercanos también obtendrán un id de cluster. ¿No está de acuerdo?

2 votos

Sí, probablemente. Siempre he puesto array_agg(cluster_id) como cluster_ids en el inner select y luego he utilizado WHERE array_length(cluster_ids, 1) > 1 para este tipo de lógica, pero tu enfoque es más sencillo. Probablemente deberías explicarlo en la respuesta, ya que ClusterDBScan no es muy obvio cuando lo ves por primera vez +1 de todas formas, esta es realmente una de mis funciones favoritas, tiene tantos usos interesantes, que son realmente dolorosos de hacer de la manera antigua con self joins espaciales.

2voto

Cyril Puntos 141

Este es mi enfoque,

Se denomina "agrupación del buffer a la distancia requerida"

(no te alejes de los peces de la manada a la distancia especificada, y entonces te comeremos :-)),

Consta de 6 puntos, nadando...

Los datos de origen mostrados en la figura 1 enter image description here

Se trata de polígonos de tipo poligonal. Las restricciones, el ejemplo, se muestran sin la semántica del objeto, para que pueda guardarlo usted mismo.

1) Cree un búfer que equivalga a casi la mitad de la distancia requerida, por ejemplo 501 m:

create table polygons_byf as SELECT ((ST_Buffer(geography(geom),501))::geometry) as geom FROM polygons;

2) Polígono disolvente:

create table polygons_byf_dump as select st_buffer( (st_dump( st_union( st_buffer(geom, 0.0000000001)))).geom, -0.0000000001) as geom FROM polygons_byf;

(John Powell :-)...)

ver figura 2

enter image description here

3) Crear el punto mediano al polígono original:

create table polygons_byf_centr as SELECT ST_PointOnSurface(geom) as geom FROM polygons;

ver figura 3

enter image description here

4) Cuente el número de puntos que caen en los polígonos combinados:

create table polygons_pt_count as SELECT b.geom, count (*) as cnt FROM polygons_byf_centr a, polygons_byf_dump b WHERE st_intersects(a.geom, b.geom) GROUP BY b.geom ORDER BY b.geom;

ver figura 4

enter image description here

5) Eliminar los polígonos que sólo tienen un punto:

DELETE from polygons_pt_count WHERE cnt = '1';

ver figura 5

enter image description here

6) Seleccionar sólo los polígonos que cumplen nuestra condición:

create table polygons_sel as SELECT ST_Intersection(a.geom, b.geom) as geom FROM polygons_pt_count a, polygons as b WHERE ST_Intersects (a.geom, b.geom)

ver figura 6

enter image description here

7) Eso es todo, este es nuestro resultado.

2voto

evojacking Puntos 21
SELECT id
FROM polygons
WHERE id IN (
    SELECT
        p1.id
    FROM polygons p1
    JOIN polygons p2 ON (ST_DWithin(p1.geom, p2.geom, 1000))
    WHERE p1.id <> p2.id
);

Puedes unir polígonos en ST_Dwithin para encontrarlas estando como máximo a un kilómetro de distancia de otras. Tenga en cuenta que la distancia que se utiliza se da en unidades SRID, así que tenga cuidado al utilizar los grados.

Supongo que el índice GIST en geom campo, así como PRIMARY KEY en id existe el campo. Como se indica en la documentación, ST_Dwithin incluye la comparación de bboxes y, en general, debería ser más rápido que construir buffers alrededor de las geometrías de entrada.

0 votos

Esta función ST_DWithin incluye automáticamente una comparación de bounding box, por lo que su uso es menos preciso, por lo que la he abandonado, pero tu solución también me parece interesante, y la abundancia de respuestas enriquece la pregunta, respetuosamente...

1 votos

La comparación de la caja de contención no implica que la función sea menos precisa. Implica que la función utilice bbox para prefiltrar los datos.

0 votos

Pasando a la función ST_Expand - lo que ella hace ...: -)...

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