10

I've seen a lot of questions involving splitting a line with the help of a point layer.

I want to split a line into fractions of its length.

For example, I have a line 400 meters long, I want to split it into four lines of 100 meters long each.

There is the grass module v.split, but I get an error message when I start it from the qgis toolbox :

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

So I'm not sure if I get it to work if this would be a solution.

  • Please clarify: Do you want to split by length i.e. ever 100 meters or into a specific number of parts? – underdark Oct 6 '14 at 18:25
  • Into a specific number of parts. Joseph, below, has given a good workaround. – Gilles Oct 22 '14 at 15:34
9

The v.split.length function from GRASS should do exactly what you want by splitting the line into equal segments defined by the user without the need for a point layer. Here's a simple example of a straight line (it also works on non-straight and multiple lines):

Simple line

I added a column to calculate its length using $length in the expression:

Line attribute

Using the v.split.length function from GRASS via the Processing Toolbox, I chose to split the line into 25m segments which should make a total of 4 parts:

v.split.length function

I then updated the Length column of the output layer and used the same command as above to re-calculate the length:

Attribute result

Not sure why you are receiving the error, could you share your line layer for people to test?

  • Hello, thanks for your answer. It is working. It's not splitting the line in fractions of the lenght though, as I still have to calculate the number of segments from the measured length, but it's a good workaround. Thank you. – Gilles Oct 22 '14 at 15:31
  • 2
    If the "Maximum segment length" is set to 25 why did you get 4 segment longer than 25 (25.465) and not 5 segment (4 of 25 and one of 1.86 or 5 of 20,372 if the tool output equal length) ? – J.R Oct 23 '19 at 12:00
  • 1
    @J.R - That's a good question to ask 5 years ago :). I don't have an answer to that, perhaps it was a bug in the tool considering it would have been an old QGIS version. Also, as it was in my early days of learning GIS, I should have used another CRS when measuring accurate distances in meters! – Joseph Oct 23 '19 at 12:08
  • 1
    @Joseph, I think you would choose PyQGIS today, do not you? =) – Taras Oct 23 '19 at 12:14
  • 1
    @Taras - I would be more inclined, yes :) – Joseph Oct 23 '19 at 12:22
2

Tested on QGIS 2.18 and QGIS 3.4

Let's assume there is a polyline layer called "lines".

input

I can suggest using a "Virtual Layer" through Layer > Add Layer > Add/Edit Virtual Layer...


There are possible several cases:


Case 1. Splitting the line into equal segments, basically equal length which is defined by the user.

With the following Query, it is possible to achieve the result. To increase/decrease the segment length, please adjust the 1000 AS step_length in -- 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

The output Virtual Layer will look as following

output_1

Note: If 'delta' (e.g. the last shortest segment) should not be included, then insert WHERE sec_length >= step_length in -- query, see below

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

Case 2. Splitting the line into a certain number of segments

With the following Query, it is possible to achieve the result. To increase/decrease the number of segments, please adjust the 8 AS sections in -- 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

The output Virtual Layer will look as following

output_2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.