5

I have a several line features stored as shapefiles, obviously constructed of several connecting segment.

I wish to export the attribute tables of each feature as a CSV to use in a separate spreadsheet. However, this requires the comprising segments being ordered in the order which they comprise the line (i.e. the bottom left segment first and the top right segment last). Is there an algorithm or tool I could use to achieve this? Ideally it would assign each segment an ID based on its location in the line feature, incrementing from the start of the line (0) to the end.

I have calculated the start/end points of each line segment but unfortunately cannot simply sort by these coordinates as the lines do not run in a continuous direction.

Expanded information: My data is a section of a road network stored as a single polyline. This line is comprised contains a number of features, each with information of their length and average travel time (see picture):

enter image description here

I actually have several lines, each one representing a direction of travel across a route in the road network.

I have exported the line features to a CSV so that I can compare the travel times across the routes with those produced with a traffic model. However, in order to compare like-for-like I need each feature to be in order as they form the line. Currently, each feature in the attribute table corresponds to a random section of the route - I wish to sort these features so that they appear in the order which they form the line.

4
  • 1
    thanks for clarifying. if your segments are running in different directions (some head-to-tail, some head-head), then the plugin Join Multiple Lines can help sort them into one continuous line going in one direction. It should work so long as you don't have loops or branches in your network. I'm not sure if it can help if your segments are completely random order, though.
    – Steven Kay
    Sep 25, 2017 at 8:22
  • All of the segments run in the same direction along the road network. The issue is that in the attribute table there is no way of sorting them into this order from start to finish which is the format which I need them in. I'm thinking that the best option will be just to write a python script to do this via the connections between start/end nodes of each segment.
    – JoeTea
    Sep 25, 2017 at 8:32
  • Could the Toid field on your screenshot be in sequence as per your line?
    – Kazuhito
    Sep 25, 2017 at 9:29
  • Sadly not, unfortunately I have to use the data as given and in this case it isnt very helpfully organised!
    – JoeTea
    Sep 25, 2017 at 10:12

3 Answers 3

4

Following the above advice by @StevenKay this small experiment worked for me. Please note this is tested on 1 set of line segments.

Overall this goes like this:

  1. Join line segments into one line by Join Multiple Lines. This sorts the order and direction of segments.
  2. Split the line again into segments. (Explode lines)
  3. Look up the id field of the original line segments (refFunctions)
  4. Join attribute tables, using the id fields.

First, I have this collection of random line segments

enter image description here

By Join Multiple Lines plugin, segments are combined into single line. Most importantly it becomes continuous and orderly (see comments by Steven Kay). At the same time attribute table loses rows except for the first one.

enter image description here

Then I split the line by Explode lines in the processing toolbox.

enter image description here

As I already have refFunctions plugin, just opened the attribute table of Exploded and created a new field "original" by expression geomequals('original_lines', 'id').

enter image description here

Above picture looks exactly same as the original random line segments. Their difference is only the order of segments.

Now I can Join the attribute table of original layer and this sorted layer, to get the final product.

1
  • 1
    I believe this will be a very helpful answer for some people +1. In my case, unfortunately the original line has 89 features, the merged line just 1 (obviously), and the exploded line has 384 features. Thus the refFunction join does not work for me as in your example. I have gone ahead and spent a few hours manually ordering my lines as I had time constraints. Next time I shall probably write a python script to achieve this based on the xy coordinates of the overlapping start/end points of the route. Thank you for all your help however, it is appricated!
    – JoeTea
    Sep 26, 2017 at 13:02
3

you could use the GRASS tool v.split.vert in Processing

This can break a linestring out into individual segments.

Here's an example line I've drawn, with 5 segments. This one starts in Edinburgh and goes counter-clockwise.

enter image description here

Choose your line layer, then apply v.split.vert. Make sure you set the "Maximum number of vertices in segment" to 2.

Now, each of your individual line segments is a separate line feature. If your lines have any other attributes, these should be duplicated for the individual line segments. They should appear in the same order that the line was traced.

Open this generated layer for editing.

Add 4 columns, called start_x, start_y, end_x, end_y. These should all be of type real, width 12, precision 6.

Use the following functions for each of your new fields. You can apply these in the Attribute Table,

start_x : $x_at(0)
start_y : $y_at(0)
end_x : $x_at(1)
end_y : $y_at(1)

Once these fields have been added, and the layer saved, you can save your layer as CSV format.

You should now have your start/end points for each line segment on its own row, as shown here in LibreOffice...

enter image description here

If you want to number individual segments within each line, this can be done using some of the neat new aggregation functions

To add this,

  • make sure you have a field (e.g. fid) which is unique for each of your original lines (1, 2, 3...)
  • add an integer field called unid which uses $rownumber. This is unique for each line segment in the split layer.
  • add an integer field called segnumber

The segnumber field should use...

1 + unid - minimum("unid","fid")

That will number your line segments within each line...

enter image description here

2
  • Hello and thank you for your answer. Unfortunately this does not achieve what I need. The last section seems the most promising but my segnumber field does not report a unique number for each feature for my line. I have expand my question above with more information
    – JoeTea
    Sep 25, 2017 at 8:06
  • Thanks a lot for the advice @Steven Kay, everything worked very well for me, generating unique IDs for all segments ordered per route for a complete city!
    – Birgit
    Jan 21, 2018 at 18:51
2
  1. Make centroids for each line (Vector geometry>Centroids)
  2. Use Network analysis>Shortest path (layer to point)
  3. In an attribute table sort by cost column
  4. You can use Vector table>Add autoicremental field

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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