Download River Data from OpenStreetMap, Resort River Path, and Generate Milestones for a River: Basic GIS for Kayaking

Jack Lee
JackOnTheRoad
Published in
8 min readDec 10, 2023

This blog post is the script for my YouTube video. So, it can be more casual and less concise. In the article, I can only show you the key steps. As there are too many detailed steps, listing all of them is not efficient. You can watch my video or others’ videos about the common usage of QGIS.

Basic GIS for Kayaking.

All the Python Scripts and related files in this project have been uploaded to GitHub.

In my last blog post, I talked about basic river geo-information and its use cases for kayaking, including river network, river path, elevation profile, milestones of a river, and dams on a river.

River Geo Analysis for Kayaking — Basic GIS for Kayaking | by Jack Lee | JackOnTheRoad | Dec, 2023 | Medium

Han River and Jialing River
Milestones imported into the Gaia GPS app
Haihe River Basin with Yongind River Highlighted
Elevation Profile of Yongind River

In this article, only the most important steps will be covered.

Required Plugins for QGIS.

Prerequisites

  • Select the intersection of two layers of vectors and Export it using QGIS.
  • Basic vector editing skills like select, copy, paste, or delete a feature from vectors.
  • Download the shapefile of the river basin from hydrosheds.org. And export any specific river basin you want.

Why do I need river data from OpenStreetMap?

Before I thought about retrieving data from OpenStreetMap, I had already downloaded the river network data from hydrosheds.org. But it’s not accurate. It cannot be used to generate Elevation Profile and Milestones. So, I need to download river data from OpenStreetMap.

River Network Data from hydrosheds.org is not accurate.

River Data from hydrosheds.org is not accurate.

Download River Data from OpenStreetMap.

Download River Data from OpenStreetMap using QuickOSM.
  • You need to care about all the parameters in the red box.
  • The source of a river may be a creek, so we need to download two types of waterways. One is a river, and the other is a stream.
  • The conjunction between the query items of river and stream is OR.
  • The search zone I’m using is a specific river basin extracted from the basin data of hydrosheds.org.
Query Result from OSM and the Search Rang of Xiang River Basin.
  • The search results are three different layers. Points, Lines, and Polygons.
  • The layer of Lines is the only one we want. Because rivers are lines. The others can be cleared.
  • Using QuickQSM, we can download anything from OSM. Like dams, routes, power grids, etc.
  • If you don’t know the name of the data type, just zoom in and search with the query parameters as empty. Then, open the attribute table of the search result. You can see the data type of the one you wanted.

Next, extract a single river path from the river network.

Use the plugin flow trace

Use the downstream function of the flow trace plugin with the river source selected first.
  • Select the source segment of the river you want.
  • Run flow trace with the parameter tolerance as 0 and downstream selected.
  • If you get a complete river path from the source to the river mouth. Congratulation. Export the selected features (river path) to a shapefile.
  • If you don’t get a complete river path but only a portion of the river. Use select by intersection with the river basin layer and export the selected features (river network) to a shapefile. (Vector > Research tools > Select by Location)

Use a Python script to process the shapefile we just exported.

osm_river_shp_resort.py
  • For now, we have a shapefile of a river path or a river network.
  • Change the input parameters in osm_river_shp_resort.py.
  • The script requires three parameters. The first one is the file path of the shapefile.
  • The second one is the starting segment osm_id of the river path. Select the first segment and open the attribute table; you can see the feature highlighted and copy the osm_id.
  • The third parameter is a set of ending segments osm_id. It means you can input multiple osm_id separated by commas. Of course, it’s okay to just input one. The reason for multiple ending ids is that the mouth of a river may not be a single path, there are so many rivers empty into the ocean with being split into multiple routes.
  • If there are branches in the middle or the end of a river, the script will choose one randomly.
  • If there is a dead end in some branch, the script will output an error with the osm_id. You need to solve it by yourself. Manually delete the branch.
  • The output file is like this, and xxx is its original name. XXX_sorted.shp.
  • So, the function of the Python script is that. At first, get the starting segment, then downstream all the way to the ending segments, and get all the segments along the way in order.

At the last step, we may already get a river path. Why do we need to get it sorted?

  • The river path was selected by the plugin flow trace.
  • The shapefile of the river path is a collection of small segments. They are not placed in the order of downstream.
  • No matter whether generating an Elevation Profile or Milestones, what we need is a single line without branches. But typically, there are many branches on a river.
  • If the input file is a river network, the script will also automatically select all the segments along the way from the source to the river mouth. It may take more seconds to run.

Dissolve the segments.

  • For now, we have the shapefile with all segments sorted.
  • What we want is a shapefile with no segments.
  • Use the dissolve function. Vector > Geoprocessing Tools > Dissolve.
  • Export the dissolved layer as a new shapefile and a KML file.

Generate Elevation Profile.

  • Open the KML file in Google Earth.
  • Right-click on the file in Google Earth, and select the item “Show Elevation Profile”.
Elevation Profile of Xiang River.

Generate Milestones of a river.

Use a Python script generate_milestones_along_path.py.

  • Only one input parameter is the shapefile of the river path without segments.
  • The output file is xxx_milestones.shp. Its original file name is xxx.shp.
  • The script uses Great circle algorithm with the Earth's Radius equal to 6378137 meters to calculate the distance. If you want to use the average Radius of Earth 6373 km, you can change the R manually.
  • Or, If you want to calculate the distance using the algorithm regarding Earth as an ellipsoid. You need to comment and uncomment two lines of code in the script.
  • Open the file xxx_milestones.shp in QGIS. Export it as a KML or GPX file to import into the Gaia GPS app.
Uncomment these two lines to calculate the distance by treating the earth as an ellipsoid.

Compare the distance generated by the Python script with the path distance on the Gaia GPS app.

  • Open the attribute table of the milestones shapefile.
  • Look at the last row. The distance of the river path is the value in the column “seg_distance”
  • Import both the river path KML file and river milestones KML file into the Gaia GPS app.
  • The distances are the same, 535.17 KM. The distance calculated by the Python script is accurate.
River Path distance of Dongjiang River calculated by the Python script.
The distance calculated by Gaia GPS app.

Why didn’t I use the QGIS built-in function Points along geometry?

  • “Points along geometry” uses the projection reference coordinate system to calculate distance. It’s not accurate.
  • Using different projection coordinate systems will result in varying distances calculated by this plugin.
  • I couldn’t find any plugin that can make it. So, I made a script myself.
  • If you know a plugin with similar functions, please leave a comment below.

Download and process dam data from OpenStreetMap.

QuickOSM Query Page Searching Dams in a Basin.
Search Result for the Dams in the Basin.
Create Buffer for the River Path — Key Step to Select the Dams Intersected with the River.
The River Paht with a Buffer to make the River Path wider.
If the Buffer is not wide enough, some Dams will be missing.
  • Search Dams in the QuickOSM plugin.
  • The search results are three layers: Points, Lines, and Polygons.
  • In this scenario, Lines and Polygons are what we need.
  • Select Lines and Polygons that intersect with the river path. And save it as a single shapefile. You need to do the action “select and save” twice. Because Lines and Polygons are different layers.
  • If there are branches, maybe one of the branches is a dam, and the other is a navigation lock. But the river path passes through the lock. If you want the dam to be selected, you need to increase the width of the river path.
  • Create a buffer for the river to increase the width so as to cover the dams. Vector > Geoprocessing Tools > Buffer.
  • Check if the buffer is wide enough to cover the dam.
  • For now, what we get are two shapefiles of Lines and Polygons.
  • Convert Polygons to Lines and then merge two vector layers of Lines into one. Different types of vector layers, like lines and polygons, cannot be merged into one, so we need to convert it first.
  • For now, we have one shapefile containing all the dams on the river.

Related Resources

Beautiful Relief Basemap from https://maps-for-free.com/

  • Tile Server for base map

https://maps-for-free.com/layer/relief/z{z}/row{y}/{z}_{x}-{y}.jpg

  • Tile Server for rivers

https://maps-for-free.com/layer/water/z{z}/row{y}/{z}_{x}-{y}.gif

  • zmax=11
  • Tile Server URLs were captured by Fiddler (an HTTP traffic capture tool)

--

--

Jack Lee
JackOnTheRoad

A big fan of kayaking and geography. Traveling around China by kayaking now. YouTube JackOnTheRoad_en .