Jak podzielić linię na określoną liczbę części?


11

Widziałem wiele pytań dotyczących podziału linii za pomocą warstwy punktowej.

Chcę podzielić linię na ułamki jej długości.

Na przykład mam 400metr długości, chcę podzielić go na cztery linie o długości 100 metrów każda.

Istnieje moduł trawy v.split, ale pojawia się komunikat o błędzie, gdy uruchamiam go z przybornika qgis:

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

Nie jestem więc pewien, czy uda mi się to uruchomić, jeśli byłoby to rozwiązanie.


Proszę wyjaśnić: czy chcesz podzielić według długości, tj. Kiedykolwiek 100 metrów czy na określoną liczbę części?
podmroku

Na określoną liczbę części. Joseph poniżej dał dobre obejście.
Gilles

Odpowiedzi:


10

Funkcja v.split.length z GRASS powinna robić dokładnie to, co chcesz, dzieląc linię na równe segmenty zdefiniowane przez użytkownika bez potrzeby stosowania warstwy punktowej. Oto prosty przykład linii prostej (działa również na nieprostych i wielu liniach):

Prosta linia

Dodałem kolumnę, aby obliczyć jej długość za pomocą $lengthwyrażenia:

Atrybut linii

Korzystając z funkcji v.split.length z GRASS za pośrednictwem Processing Toolbox , zdecydowałem się podzielić linię na 25m segmenty, które powinny składać się w sumie z 4 części:

v. podświetlona funkcja długości

Następnie zaktualizowałem kolumnę Długość warstwy wyjściowej i użyłem tego samego polecenia, co powyżej, aby ponownie obliczyć długość:

Wynik atrybutu

Nie masz pewności, dlaczego pojawia się błąd, czy możesz udostępnić warstwę linii użytkownikom do przetestowania?


Witam, dziękuję za odpowiedź. To działa. Nie dzieli jednak linii na ułamki długości, ponieważ wciąż muszę obliczyć liczbę segmentów na podstawie zmierzonej długości, ale jest to dobre obejście. Dziękuję Ci.
Gilles

2
Jeśli „Maksymalna długość segmentu” jest ustawiona na 25, dlaczego otrzymałeś 4 segmenty dłuższe niż 25 (25,465), a nie 5 segmentów (4 z 25 i jeden z 1,86 lub 5 z 20 372, jeśli wydajność narzędzia jest równa)?
JR

1
@JR - To dobre pytanie, które należy zadać 5 lat temu :). Nie mam na to odpowiedzi, być może był to błąd w narzędziu, biorąc pod uwagę, że byłaby to stara wersja QGIS. Podobnie, jak to było we wczesnych latach nauki GIS, powinienem był użyć innego CRS podczas pomiaru dokładnych odległości w metrach!
Joseph

1
@Joseph, myślę, że dziś wybrałbyś PyQGIS, prawda? =)
Taras,

1
@Taras - Byłbym bardziej skłonny, tak :)
Joseph

2

Testowane na QGIS 2.18 i QGIS 3.4

Załóżmy, że istnieje warstwa polilinii o nazwie "lines".

Wejście

Mogę zaproponować użycie „Wirtualnej warstwy” przez Layer > Add Layer > Add/Edit Virtual Layer...


Możliwych jest kilka przypadków:


Przypadek 1. Podział linii na równe segmenty, w zasadzie równa długość, którą określa użytkownik.

Za pomocą następującego zapytania można osiągnąć wynik. Aby zwiększyć / zmniejszyć długość segmentu, dostosuj wartość 1000 AS step_lengthw -- 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

Wyjściowa warstwa wirtualna będzie wyglądać następująco

wyjście_1

Uwaga: Jeśli „delta” (np ostatni segment najkrótsza) nie powinny być włączone, a następnie włożyćWHERE sec_length >= step_lengthw-- query, patrz poniżej

-- 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

Przypadek 2. Podział linii na określoną liczbę segmentów

Za pomocą następującego zapytania można osiągnąć wynik. Aby zwiększyć / zmniejszyć liczbę segmentów, dostosuj wartość 8 AS sectionsw -- 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

Wyjściowa warstwa wirtualna będzie wyglądać następująco

wyjście_2

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.