Як розділити лінію на конкретну кількість частин?


11

Я бачив багато питань, пов’язаних з розділенням лінії за допомогою точкового шару.

Я хочу розділити лінію на частки її довжини.

Наприклад, у мене 400довжина ліній метрів, я хочу розділити її на чотири лінії довжиною 100 метрів кожна.

Існує модуль трави v.split, але я отримую повідомлення про помилку, коли запускаю його з панелі інструментів qgis:

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

Тож я не впевнений, чи змушу це працювати, якщо це буде рішенням.


Будь ласка, уточніть: Ви хочете розділити довжину, тобто колись 100 метрів, або на певну кількість частин?
андермаркет

У певну кількість частин. Внизу Йосип дав добрий спосіб.
Жиль

Відповіді:


10

Функція v.split.length від GRASS повинна робити саме те, що ви хочете, розділивши лінію на рівні сегменти, визначені користувачем, не потребуючи точкового шару. Ось простий приклад прямої лінії (вона також працює на не прямих та декількох лініях):

Проста лінія

Я додав стовпчик для обчислення його довжини, використовуючи $lengthу виразі:

Атрибут рядка

Використовуючи функцію v.split.length від GRASS через панель інструментів обробки , я вирішив розділити лінію на 25м сегменти, які повинні складати загалом 4 частини:

v.split.length функція

Потім я оновив стовпчик "Довжина" вихідного шару і використав ту ж команду, що і вище, щоб перерахувати довжину:

Атрибутивний результат

Не знаєте, чому ви отримуєте помилку, чи можете ви поділитися шаром ліній для тестування людей?


Привіт, дякую за вашу відповідь. Це працює. Це не розбивання лінії на частки довжини, хоча я все ще повинен обчислити кількість відрізків від вимірюваної довжини, але це вдалий обхід. Дякую.
Жиль

2
Якщо "Максимальна довжина сегмента" встановлена ​​на 25, чому ви отримали 4 сегмент довше 25 (25,465), а не 5 сегмент (4 з 25 і один 1,86 або 5 з 20,372, якщо вихід інструменту дорівнює довжині)?
JR

1
@JR - Це гарне запитання, яке потрібно задати 5 років тому :). У мене немає відповіді на це, можливо, це помилка в інструменті, вважаючи, що це була б стара версія QGIS. Крім того, як це було в мої перші дні вивчення ГІС, я повинен був використовувати інший CRS при вимірюванні точних відстаней у метрах!
Йосип

1
@ Джозеф, я думаю, ти б вибрав PyQGIS сьогодні, чи не так? =)
Тарас

1
@Taras - Я був би більш схильний, так :)
Йосип

2

Тестували на QGIS 2.18 та QGIS 3.4

Припустимо, існує полілінійний шар, який називається "lines".

вхід

Я можу запропонувати використовувати "Віртуальний шар" наскрізь Layer > Add Layer > Add/Edit Virtual Layer...


Можливо кілька випадків:


Випадок 1. Розбиття лінії на рівні відрізки, в основному однакова довжина, яку визначає користувач.

За допомогою наступного Запиту можна досягти результату. Для того, щоб збільшити / зменшити довжину сегмента, будь ласка , налаштуйте 1000 AS step_lengthв системі -- 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

Вихідний віртуальний шар буде виглядати наступним чином

вихід_1

Примітка: Якщо значення «дельта» (наприкладостанній сегмент найкоротшого) не повинен бути включений,потім вставитиWHERE sec_length >= step_lengthв-- queryсм нижче

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

Випадок 2. Розбиття рядка на певну кількість сегментів

За допомогою наступного Запиту можна досягти результату. Для того, щоб збільшити / зменшити кількість сегментів, будь ласка , налаштувати 8 AS sectionsпо прибуттю -- 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

Вихідний віртуальний шар буде виглядати наступним чином

вихід_2

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.