¿Cómo dividir la línea en un número específico de partes?

11

He visto muchas preguntas que implican dividir una línea con la ayuda de una capa de puntos.

Quiero dividir una línea en fracciones de su longitud.

Por ejemplo, tengo una línea de 400metros de largo, quiero dividirla en cuatro líneas de 100 metros de largo cada una.

Existe el módulo grass v.split, pero recibo un mensaje de error cuando lo inicio desde la caja de herramientas qgis:

*"TypeError: object of type 'NoneType' has no len()"*

Así que no estoy seguro si lo hago funcionar si esto sería una solución.

Gilles
fuente
Por favor aclare: ¿Desea dividir por longitud, es decir, cada 100 metros o en un número específico de partes?
oscuro
En un número específico de partes. Joseph, abajo, ha dado una buena solución.
Gilles

Respuestas:

10

La función v.split.length de GRASS debe hacer exactamente lo que desea dividiendo la línea en segmentos iguales definidos por el usuario sin la necesidad de una capa de puntos. Aquí hay un ejemplo simple de una línea recta (también funciona en líneas no rectas y múltiples):

Linea simple

Agregué una columna para calcular su longitud usando $lengthla expresión:

Atributo de línea

Usando la función v.split.length de GRASS a través de Processing Toolbox , elegí dividir la línea en segmentos de 25 m que deberían formar un total de 4 partes:

Función v.split.length

Luego actualicé la columna Longitud de la capa de salida y usé el mismo comando que el anterior para volver a calcular la longitud:

Resultado de atributo

No estoy seguro de por qué está recibiendo el error, ¿podría compartir su capa de línea para que la gente la pruebe?

Joseph
fuente
Hola gracias por tu respuesta Está funcionando. Sin embargo, no está dividiendo la línea en fracciones de la longitud, ya que todavía tengo que calcular el número de segmentos a partir de la longitud medida, pero es una buena solución. Gracias.
Gilles
2
Si la "Longitud máxima del segmento" se establece en 25, ¿por qué obtuvo 4 segmentos más largos que 25 (25.465) y no 5 segmentos (4 de 25 y uno de 1.86 o 5 de 20,372 si la salida de la herramienta es igual a la longitud)?
JR
1
@JR - Esa es una buena pregunta para hace 5 años :). No tengo una respuesta para eso, tal vez fue un error en la herramienta teniendo en cuenta que habría sido una versión antigua de QGIS. Además, como era en mis primeros días de aprendizaje de SIG, ¡debería haber usado otro CRS al medir distancias precisas en metros!
Joseph
1
@ Joseph, creo que elegirías PyQGIS hoy, ¿no? =)
Taras
1
@Taras - Estaría más inclinado, sí :)
Joseph
2

Probado en QGIS 2.18 y QGIS 3.4

Supongamos que hay una capa de polilínea llamada "lines".

entrada

Puedo sugerir el uso de una "Capa virtual" a través de Layer > Add Layer > Add/Edit Virtual Layer...


Hay varios casos posibles:


Caso 1. Dividir la línea en segmentos iguales, básicamente de la misma longitud definida por el usuario.

Con la siguiente consulta, es posible lograr el resultado. Para aumentar / disminuir la longitud del segmento, ajuste el 1000 AS step_lengthen -- configurations.

-- generate series
WITH RECURSIVE generate_sections(id, sec) AS (
SELECT conf.start + 1, conf.start
FROM conf
UNION ALL
SELECT id + conf.step, sec + conf.step_length/conf.length_line
FROM generate_sections, conf
WHERE sec + conf.step_length/conf.length_line <= 1
),

-- configurations
conf AS (
SELECT
0.0 AS start,
1.0 AS step,
1000 AS step_length,
ST_Length(l.geometry) AS length_line
FROM lines AS l
)

-- query
SELECT gs.id AS id,
        ROUND(ST_Length(ST_Line_Substring(l.geometry, start + sec, sec + conf.step_length/conf.length_line)),0) AS seg_length,
        ST_Line_Substring(l.geometry, start + sec, sec + conf.step_length/conf.length_line) AS geom
FROM generate_sections AS gs, lines AS l, conf
GROUP BY gs.id

La capa virtual de salida tendrá el siguiente aspecto

salida_1

Nota: Si 'delta' (por ejemplo, el último segmento más corto) no debe ser incluida, a continuación, inserteWHERE sec_length >= step_lengthen-- query, ver más abajo

-- query
SELECT gs.id AS id,
        ROUND(ST_Length(ST_Line_Substring(l.geometry, start + sec, sec + conf.step_length/conf.length_line)),0) AS seg_length,
        ST_Line_Substring(l.geometry, start + sec, sec + conf.step_length/conf.length_line) AS geom
FROM generate_sections AS gs, lines AS l, conf
WHERE seg_length >= step_length
GROUP BY gs.id

Caso 2. División de la línea en un cierto número de segmentos.

Con la siguiente consulta, es posible lograr el resultado. Para aumentar / disminuir el número de segmentos, ajuste el 8 AS sectionsen -- configurations.

-- generate series
WITH RECURSIVE generate_sections(id, sec) AS (
SELECT conf.start + 1, conf.start
FROM conf
UNION ALL
SELECT id + conf.step, sec + conf.step
FROM generate_sections, conf
WHERE sec + conf.step < conf.sections
),

-- configurations
conf AS (
SELECT
8 AS sections,
0.0 AS start,
1.0 AS step
)

-- query
SELECT gs.id AS id,
    ST_Line_Substring(l.geometry, conf.start + sec/conf.sections, sec/conf.sections + step/conf.sections) AS geom,
    ROUND(ST_Length(ST_Line_Substring(l.geometry, conf.start + sec/conf.sections, sec/conf.sections + step/conf.sections)),2) AS seg_length
FROM generate_sections AS gs, lines AS l, conf
WHERE start + step < sections
GROUP BY gs.id

La capa virtual de salida tendrá el siguiente aspecto

salida_2

Taras
fuente