7 votos

Opuesto a ST_intersection

Estoy tratando de recortar una serie de líneas seleccionando sólo la parte de la geometría fuera de un polígono utilizando PostGIS.

De mi lectura sobre lo que st_intersection es decir, devuelve una geometría que representa la parte compartida de geomA y geomB. Me gustaría hacer lo contrario de esto, es decir, devolver la geometría que no es compartida por geomA y geomB.

He estado tratando de trabajar con st_difference que debería devolver una geometría que representa la parte de la geometría A que no se cruza con la geometría B. Pero estoy teniendo algunos problemas para obtener el resultado que quiero. Esto es lo que he escrito hasta ahora...

SELECT
    t.id, ST_Difference(t.the_geom_webmercator, t1.dock) as intersection
FROM
    trips t, 
    (select
        d.id, d.name,ST_Buffer(ST_Centroid(the_geom_webmercator),1000) as dock
    from 
        docks d) as t1
WHERE 
    ST_Intersects(t.the_geom_webmercator,t1.dock)
    t.id IN (25558, 25555, 25553, 25533, 25517, 25523, 25501, 25506,25532,25439)
    and ST_Difference(t.the_geom_webmercator, t1.dock) is not null

Esto devuelve

  • las líneas rosas son el resultado de la consulta anterior, por lo que algunas líneas se detienen en los límites del círculo y otras no
  • los círculos son los polígonos por los que quiero recortar todo,
  • la línea de puntos subyacente es el resultado de básicamente la misma consulta que la anterior, sustituyendo st_intersection con st_difference que devuelve la inversa del resultado deseado, es decir, las geometrías dentro de los círculos.

¿Alguna sugerencia para modificar esta consulta? enter image description here

1 votos

Construiría la intersección y luego quitaría esos puntos del total. Otra posibilidad es construir un compuesto de todos los círculos y luego hacer la operación. No puedes hacerlo uno por uno porque mientras un punto está en un círculo, no está intersectando la mayoría de los otros círculos.

6voto

NilObject Puntos 7874

Conseguir una diferencia "intuitiva" es, por desgracia, un poco intensivo en cuanto a la CPU, pero se puede hacer. La idea principal es que hay que utilizar sólo un diferenciador, de lo contrario se obtiene un montón de diferencias por pares, que no es lo que se quiere intuitivamente.

WITH d AS (
    SELECT ST_Union(ST_Buffer(ST_Centroid(the_geom_webmercator),1000)) AS the_geom_webmercator
    FROM docks
)
SELECT
    CASE WHEN ST_Intersects(d.the_geom_webmercator, t.the_geom_webmercator)
    THEN ST_Difference(t.the_geom_webmercator, d.the_geom_webmercator)
    ELSE t.the_geom_webmercator
    END AS the_geom_webmercator
FROM d, trips t
WHERE t.id IN (25558, 25555, 25553, 25533, 25517, 25523, 25501, 25506,25532,25439)

(Como nota al margen, un búfer de 1000 metros de un objeto en web mercator no es un verdadero búfer de 1km en ningún sitio que no sea el ecuador, así que cuidado que no te muerde).

Lo anterior es un poco descabellado, y se puede hacer más eficiente (a veces) para conjuntos de datos más grandes mediante la unión de los búferes en múltiples diferenciadores, uno para cada viaje que van a diferencia. La eficiencia relativa del segundo enfoque depende de cuántos viajes hay frente a cuántos muelles.

0 votos

Perfecto, muchas gracias. No había pensado en la unión de los buffers y no había experimentado una declaración de caso antes. Gracias por la ayuda y la lección.

0 votos

Alguna idea sobre el uso de ST_Disjoint como se sugiere (y se discute) aquí: gis.stackexchange.com/questions/210387/

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