Как разбить линию на определенное количество частей?

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 через Processing Toolbox , я решил разделить линию на 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

Выходной виртуальный слой будет выглядеть следующим образом

OUTPUT_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

Выходной виртуальный слой будет выглядеть следующим образом

output_2

Тарас
источник