7 votos

Cálculo de la longitud de las líneas limítrofes comunes de dos polígonos en QGIS

Tengo un mapa que consta de varios distritos. ¿Cómo puedo estimar la longitud del límite común compartido por dos distritos/polígonos correspondientes en QGIS?

Por ejemplo, si un polígono "A" comparte un límite común con los polígonos "B", "C" y "D". Entonces, ¿cuál sería la longitud del límite entre los polígonos "A-B", "A-C" y "A-D"?

He calculado el polígono vecino utilizando lo siguiente en la calculadora de campo

aggregate( 
  layer:='file_districts',
  aggregate:='concatenate',
  expression:= DIST_ID,
  concatenator:=', ',
  filter:=touches($geometry, geometry())
)

Ahora quiero estimar la longitud de cada uno de los polígonos vecinos.

example

7voto

ARUNBALAN NV Puntos 101

Preámbulo: esta solución fue escrita antes del momento en que el autor demostró sus esfuerzos en la calculadora de campo.

En QGIS puedo sugerir el uso de un "Capa virtual" a través de Layer > Add Layer > Add/Edit Virtual Layer... .

Supongamos que tenemos una capa 'units_1' (amarillo) con sus correspondientes tablas de atributos en consecuencia, véase la imagen siguiente.

input

Caso 1. Con agregación

Con la siguiente consulta, es posible estimar la longitud de la frontera común que comparten dos distritos/polígonos cualesquiera.

SELECT
    u11.*,
    GROUP_CONCAT(u12.id || ', len:' || round(st_length(st_intersection(u11.geometry, u12.geometry)), 4), "; ") AS "neighbor_info"
FROM
    "unit_1" AS u11, "unit_1" AS u12
WHERE
    st_intersects(u11.geometry, u12.geometry)
    AND u11.id <> u12.id
GROUP BY
    u11.id
ORDER BY
    u11.id ASC

La capa virtual de salida con su tabla de atributos tendrá el siguiente aspecto

output1

Caso 2. Sin agregación

En caso de que no haya que realizar ninguna agregación, se procederá a la siguiente consulta

SELECT
    u11.*,
    u12.id || ', len:' || round(st_length(st_intersection(u11.geometry, u12.geometry)), 4) AS "neighbor_info"
FROM
    "unit_1" AS u11, "unit_1" AS u12
WHERE
    st_intersects(u11.geometry, u12.geometry)
    AND u11.id <> u12.id
ORDER BY
    u11.id ASC

Entonces la nueva capa virtual de salida con su tabla de atributos tendrá el siguiente aspecto

output2

6voto

Braiam Puntos 120

De forma similar a la respuesta de @Taras, puedes crear una capa virtual para obtener las líneas de borde reales, y luego calcular su longitud (o mostrarlas, o etiquetarlas, o ...)

Ir al menú Layer > Add Layer > Add/Edit Virtual Layer... e introduzca la siguiente consulta.

select a.id as poly1_id, b.id as poly2_id, 
      st_intersection(a.geometry, b.geometry) as geometry, 
      st_length(st_intersection(a.geometry, b.geometry)) as border_length
from my_layer a
    join my_layer b 
        ON st_intersects(a.geometry, b.geometry)
            AND a.id < b.id

enter image description here

Tenga en cuenta que si su capa está en lat/longs (4326), deberá utilizar st_length(st_intersection(a.geometry, b.geometry),true) as border_length en su lugar. Esta versión de st_length devolverá una distancia en metros en lugar de grados.

1voto

chhh Puntos 1154

Calcula la longitud del borde que el polígono actual comparte con todos los polígonos limítrofes, utiliza esta expresión que crea un array:

    array_foreach (
        overlay_touches (@layer, $geometry),
        length (intersection ($geometry, @element))  
    )

Convertirlo en una cadena con array_to_string() , añada el $id para identificar los polígonos y añadir otras modificaciones (véase más adelante).

Una capa de polígonos con una etiqueta generada por una expresión, basada en la expresión de arriba, que genera una lista de cadenas de texto de longitud con todos los polígonos vecinos (ver más abajo la expresión exacta utilizada aquí):

enter image description here

  • La expresión utilizada para generar la línea roja en la captura de pantalla, utilizando el generador de geometría:

    if ($id = 1, intersection ( $geometry, overlay_touches (@layer, $geometry)[0]),'')
  • Para generar la longitud de la línea límite común de los polígonos b y c almacenado en el campo denominado name utilice esta expresión (cambie el nombre y el valor de la capa en las líneas 2 y 6):

    if (
        name = 'b', 
        length(
            intersection ( 
                $geometry, 
                geometry (get_feature (@layer, 'name', 'c'))
            )
        ),
        ''
    )
  • La expresión utilizada para generar la etiqueta en la captura de pantalla - se puede utilizar sin cambios en cualquier capa de polígonos:

     'Length border of polygon '  || 
     $id || ' with: '  ||  '\n'  ||  
     array_to_string (
         array_foreach (
             overlay_touches (@layer, $id),
             '   - polygon'  || 
             @element || ': ' || 
             round (
                 length (
                     intersection (
                         $geometry, 
                         geometry (
                             get_feature_by_id (
                                 @layer, 
                                 @element
                             )
                         )
                     )
                 ), 
                 3
             ) 
         )
     )

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