Come dividere la linea in un numero specifico di parti?


11

Ho visto molte domande che coinvolgono la divisione di una linea con l'aiuto di un livello punti.

Voglio dividere una linea in frazioni della sua lunghezza.

Ad esempio, ho una linea 400lunga metri, voglio dividerla in quattro linee lunghe 100 metri ciascuna.

C'è il modulo grass v.split, ma ricevo un messaggio di errore quando lo avvio dalla casella degli strumenti qgis:

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

Quindi non sono sicuro se riesco a farlo funzionare se questa fosse una soluzione.


Si prega di chiarire: si desidera dividere per lunghezza, ovvero mai 100 metri o in un numero specifico di parti?
underdark

In un numero specifico di parti. Joseph, in basso, ha dato una buona soluzione.
Gilles,

Risposte:


10

La funzione v.split.length di GRASS dovrebbe fare esattamente quello che vuoi suddividendo la linea in segmenti uguali definiti dall'utente senza la necessità di un livello punto. Ecco un semplice esempio di linea retta (funziona anche su linee non diritte e multiple):

Linea semplice

Ho aggiunto una colonna per calcolarne la lunghezza usando $lengthnell'espressione:

Attributo di linea

Usando la funzione v.split.length di GRASS tramite la Casella degli strumenti di elaborazione , ho scelto di dividere la linea in segmenti di 25m che dovrebbero formare un totale di 4 parti:

funzione v.split.length

Ho quindi aggiornato la colonna Lunghezza del livello di output e ho usato lo stesso comando sopra per ricalcolare la lunghezza:

Risultato dell'attributo

Non sei sicuro del motivo per cui ricevi l'errore, potresti condividere il tuo livello di linea affinché le persone possano testarlo?


Ciao, grazie per la tua risposta. Funziona. Tuttavia, non sta dividendo la linea in frazioni di lunghezza, poiché devo ancora calcolare il numero di segmenti dalla lunghezza misurata, ma è una buona soluzione. Grazie.
Gilles,

2
Se la "Lunghezza massima del segmento" è impostata su 25, perché hai ottenuto 4 segmenti più lunghi di 25 (25.465) e non 5 segmenti (4 di 25 e uno di 1,86 o 5 di 20,372 se l'utensile ha la stessa lunghezza)?
JR

1
@JR - Questa è una buona domanda da porre 5 anni fa :). Non ho una risposta a questo, forse era un bug nello strumento considerando che sarebbe stata una vecchia versione di QGIS. Inoltre, come era nei miei primi giorni di apprendimento del GIS, avrei dovuto usare un altro CRS per misurare distanze precise in metri!
Joseph,

1
@Joseph, penso che oggi sceglieresti PyQGIS, vero? =)
Taras,

1
@ Taras - Sarei più propenso, sì :)
Joseph,

2

Testato su QGIS 2.18 e QGIS 3.4

Supponiamo che esista uno strato di polilinea "lines".

ingresso

Posso suggerire di utilizzare un "Livello virtuale" tramite Layer > Add Layer > Add/Edit Virtual Layer...


Esistono diversi casi:


Caso 1. Dividere la linea in segmenti uguali, sostanzialmente uguale lunghezza definita dall'utente.

Con la seguente query, è possibile ottenere il risultato. Per aumentare / ridurre la lunghezza del segmento, regolare 1000 AS step_lengthin -- 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

Il livello virtuale di output apparirà come segue

OUTPUT_1

Nota: Se 'delta' (ad esempio, l'ultimo segmento più breve) non dovrebbe essere incluso, quindi inserireWHERE sec_length >= step_lengthin-- query, vedi sotto

-- 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. Dividere la linea in un certo numero di segmenti

Con la seguente query, è possibile ottenere il risultato. Per aumentare / ridurre il numero di segmenti, regolare 8 AS sectionsin -- 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

Il livello virtuale di output apparirà come segue

output_2

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.