<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Eamon Magd</title>
    <description>The latest articles on DEV Community by Eamon Magd (@eamonmagd).</description>
    <link>https://dev.to/eamonmagd</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1835088%2F892c4d83-b231-4fb0-a1b9-9ce32e86132e.png</url>
      <title>DEV Community: Eamon Magd</title>
      <link>https://dev.to/eamonmagd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/eamonmagd"/>
    <language>en</language>
    <item>
      <title>Using Python in QGIS to scale up London's cycle infrastructure to match Amsterdam.</title>
      <dc:creator>Eamon Magd</dc:creator>
      <pubDate>Fri, 26 Jul 2024 14:17:38 +0000</pubDate>
      <link>https://dev.to/eamonmagd/using-python-in-qgis-to-scale-up-londons-cycle-infrastructure-to-match-amsterdam-504</link>
      <guid>https://dev.to/eamonmagd/using-python-in-qgis-to-scale-up-londons-cycle-infrastructure-to-match-amsterdam-504</guid>
      <description>&lt;p&gt;I've created a tutorial that shows you how to use code to scale up roads, and cycle paths, or even modify highway types between cities!&lt;br&gt;
Bonus: There's also a separate video diving deeper into a more advanced method specifically for modifying cycle paths.&lt;br&gt;
Clip from a &lt;a href="https://www.youtube.com/watch?v=fFOQ1qA4V1M" rel="noopener noreferrer"&gt;youtube &lt;/a&gt;video that shows the lack of cycle lanes in the&amp;nbsp;UKIn the UK, transport is the largest sector for carbon emissions, with cars being the main contributor. Cars even produce more emissions than planes, which is surprising! So, let's find a way to scale up cycle data using object detection and a geographic platform.&lt;br&gt;
In the UK, transport is the largest sector for carbon emissions, with cars being the main contributors. Cars even produce more emissions than planes, which is surprising! So, let's find a way to scale up cycle data using object detection and a geographic platform.&lt;br&gt;
Final output&amp;nbsp;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fijipf4bdnbha03j6bzse.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fijipf4bdnbha03j6bzse.png" alt="Image description" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Getting Polygon Data for Cycleways
&lt;/h2&gt;

&lt;p&gt;For this tutorial, we will use &lt;a href="https://qgis.org/download/" rel="noopener noreferrer"&gt;QGIS &lt;/a&gt;to modify and manage shape files (.shp), which are commonly used for maps.&lt;br&gt;
Install QuickOSM Plugin: In QGIS, go to Manage and Install Plugins, and find the QuickOSM plugin. &lt;a href="https://plugins.qgis.org/plugins/QuickOSM/" rel="noopener noreferrer"&gt;QuickOSM &lt;/a&gt; uses OpenStreetMap data to obtain cycle data.&lt;br&gt;
Configure QuickOSM: Click the QuickOSM logo. For the key, type highway, and for the value, type cycleway.&lt;br&gt;
Input Location: Under the input presets, use the dropdown to select where you want the data to be searched-for example, type London for our case. Click Run Query. Repeat this process for the other city you are interested in. Ensure to remove any layers that are points.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmtesq71ho6bzvg5gt6vh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmtesq71ho6bzvg5gt6vh.png" alt="Image description" width="800" height="706"&gt;&lt;/a&gt;&lt;br&gt;
 The output for your city's cycleway will be shown in a couple of layers from points and polygons for the city of choice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fql45sko0fg5754holg50.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fql45sko0fg5754holg50.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
London cycle infrastructure before removing point&amp;nbsp;data&lt;/p&gt;

&lt;p&gt;Delete any layers that are not line polygons so the only layer will look like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flcrgr9ez8zwsyv8vxcdy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flcrgr9ez8zwsyv8vxcdy.png" alt="Image description" width="800" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lastly do the same steps for Amsterdam so we can compare and contrast the values.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Getting the Total Length of All Cycleways
&lt;/h2&gt;

&lt;p&gt;To determine how much we need to scale the data, follow these steps:&lt;br&gt;
Open Python Console in QGIS: We'll use the qgis.core and PyQt5 modules.&lt;br&gt;
Find and Print Layers: Replace the code for layer_name with highway=cycleway.&lt;br&gt;
Calculate Total Length: Iterate through each layer, to sum up the total kilometers of cycleways. Do this for both cities (e.g., London and Amsterdam).&lt;/p&gt;

&lt;p&gt;You can run the Python code below to get the output in kilometres&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Import necessary modules
from qgis.core import QgsProject

# Print all layer names to debug and find the correct name
layer_names = [layer.name() for layer in QgsProject.instance().mapLayers().values()]
print("Available layers:", layer_names)

# Replace with the actual name of your cycleway layer
layer_name = 'highway_cycleway_Amsterdam'

# Load the layer by name
layers = QgsProject.instance().mapLayersByName(layer_name)

if not layers:
    raise ValueError(f"Layer '{layer_name}' not found. Available layers: {layer_names}")

layer = layers[0]

# Initialize total length variable
total_length = 0

# Iterate over each feature in the layer
for feature in layer.getFeatures():
    geom = feature.geometry()
    if geom:
        total_length += geom.length()

# Convert length to kilometers (assuming the layer CRS is in meters)
total_length_km = total_length  

# Print the total length in kilometers
print("Total length of cycleways in the Amsterdam: {:.2f} km".format(total_length_km))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Finding the Total Area for Your&amp;nbsp;City
&lt;/h2&gt;

&lt;p&gt;To find the rate of change, we first need a scale. For this, we'll use polygon shapefiles provided by OSM boundaries and download them for each city.&lt;br&gt;
Load Shapefiles in QGIS: Right-click the polygon layer in the layer panel. Select Open Attribute Table, then click the Field Calculator button.&lt;br&gt;
Calculate Area: Create a new field named area_km2 and use the expression $area / 1000000 to calculate the total area in square kilometres. Alternatively, you can search for the area of the cities online.&lt;br&gt;
Determine Rate of Cycle Lanes per Area: Divide the total cycleway length from Step 2 by the total area of each city to get the rate of cycle lanes per square kilometre.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft32q4cdciqodhmpdxu4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft32q4cdciqodhmpdxu4b.png" alt="Image description" width="800" height="662"&gt;&lt;/a&gt;&lt;br&gt;
Example polygon to find the total&amp;nbsp;area &lt;/p&gt;

&lt;p&gt;Calculate the Rate of Increase: Divide the rate of the city you want to scale up (e.g., London) by the rate of the reference city (e.g., Amsterdam) to get the rate of increase.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 4: Scaling the Cycleway&amp;nbsp;Data
&lt;/h2&gt;

&lt;p&gt;Finally, we'll scale the cycleways:&lt;br&gt;
Use QgsProject Package: We will use the QgsProject package and its extendLine function.&lt;br&gt;
Apply Scaling Factor: For our example, we will increase the cycleway lengths by a factor of six. This involves finding each part of the polyline and multiplying the length by six.&lt;/p&gt;

&lt;p&gt;Scaling Factor Code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
from qgis.core import QgsProject, QgsFeature, QgsGeometry, QgsPointXY, QgsVectorLayer
from PyQt5.QtCore import QVariant

# Load the layer
layer_name = 'highway_cycleway_London'
layers = QgsProject.instance().mapLayersByName(layer_name)

if not layers:
    raise ValueError(f"Layer '{layer_name}' not found.")
layer = layers[0]

# Create a new layer for the extended lines
extended_layer = QgsVectorLayer("LineString?crs={}".format(layer.crs().authid()), 
                                "extended_highway_cycle_London", "memory")
provider = extended_layer.dataProvider()
provider.addAttributes(layer.fields())
extended_layer.updateFields()

# Function to extend a line
def extend_line(line, factor):
    if line.isMultipart():
        new_points = []
        for part in line.asMultiPolyline():
            new_part = extend_single_line(part, factor)
            new_points.append(new_part)
        return QgsGeometry.fromMultiPolylineXY(new_points)
    else:
        points = line.asPolyline()
        new_points = extend_single_line(points, factor)
        return QgsGeometry.fromPolylineXY(new_points)

def extend_single_line(points, factor):
    if len(points) &amp;lt; 2:
        return points  # not enough points to extend
    start_point = points[0]
    end_point = points[-1]

    # Calculate vector from start to end
    vec_x = end_point.x() - start_point.x()
    vec_y = end_point.y() - start_point.y()

    # Extend vector
    extended_end_point = QgsPointXY(
        start_point.x() + vec_x * factor,
        start_point.y() + vec_y * factor
    )

    new_points = [start_point]
    for point in points[1:-1]:
        new_points.append(point)
    new_points.append(extended_end_point)
    return new_points

# Extend each feature and add to the new layer
for feature in layer.getFeatures():
    geom = feature.geometry()
    extended_geom = extend_line(geom, 6)
    new_feature = QgsFeature()
    new_feature.setGeometry(extended_geom)
    new_feature.setAttributes(feature.attributes())
    provider.addFeature(new_feature)

# Add the new layer to the project
QgsProject.instance().addMapLayer(extended_layer)
print("Extended lines have been created and added as a new layer.")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create Output Layer: The output layer will be named extended_highway_London for our case. By overlaying the original and scaled layers, you can see the larger scale for London if it followed the same rate of cyclists as Amsterdam.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fijipf4bdnbha03j6bzse.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fijipf4bdnbha03j6bzse.png" alt="Image description" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you enjoyed this tutorial, please check out the full video on &lt;a href="https://www.youtube.com/watch?v=fFOQ1qA4V1M&amp;amp;t=3s" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, where I use object detection on footage from London and Amsterdam and apply the rate of cyclists for an increased length.&lt;br&gt;
Have more questions? Feel free to reach out - I'm always here to help.&lt;/p&gt;

</description>
      <category>python</category>
      <category>mapping</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
