# Calculating the nearest neighbour using given road network in QGIS

I have the following information/layer:

2. Points which represent the entries to urban green spaces (point layer) - I built these cutting the roads with the borders of a polygon layer for green spaces

Now, I want to know for each address point, which is the closest entry to a green space and how far is it. For this distance calculation, I do not want to use the direct beeline, but the shortest path on the road network.

The QGIS main functions allow network analysis "layer to point", "point to layer" and "point to point". There is no layer to layer function. Is there a plugin which fits to my problem?

• You could group your adress points by their nearest green space (here bee line should do) and then run layer to point for each green space - though that would take some time.
– Erik
Jun 1, 2021 at 9:31
• Do your points lay on lines i.e. are they snapped? Can you please provide some graphic of your problem? Jun 1, 2021 at 12:16
• Providing your data (or a sample of it) would indeed help testing possible solutions. Jun 1, 2021 at 12:45

The tool to use

Iso-Area-approach can do both jobs for you, thus for each adress point, using the network:

• 1: find the closest entry to a park
• 2: get the distance to the closest park

In QGIS, use the QNEAT3 plugin with the function `Iso-Area as Pointcloud (from Layer)`. It requires two layers as input: `Network` and `Startpoint`. It then creates for every vertex of the network layer a point with the following attributes:

• `cost`: the distance along the network to the nearest feature of the `Startpoint Layer`: use the park-layer here
• `origin_point_id`: the id of the nearest feature from the `Startpoint` layer, in our case: the parks

To include the `address` layer, create additonal vertices from the address-points on the network layer. Then they will be automatically included in the output of the plugin and here we are with the result you're looking for!

The workflow in detail

I suppose the addresses (as well as the parks) are point-layers, snapped to the network. Otherwise, see at the bottom how to do that.

1. To split up the network-layer at the addresses (create new vertices), create a small line at each point of the `address`-layer. In fact, create two perpendicular lines to be sure to always get a line-split, even in the highly unlikely case when the street and the created auxiliary lines would perfectly overlap. So create two perpendicular auxiliary lines at each address point using Geometry by expression with this expression:
``````collect_geometries (
array_foreach (
array (0,90),
extend (
make_line (
\$geometry,
project (
\$geometry,
5,
)
),
5,0
)
)
)
``````

Screenshot: auxiliary lines (red lines) at each address (red points), used to split up the network (black lines) - here created with geometry generator for visualization purpose: 1. Convert the lines to single parts using `Menu Vector / Geometry tools / Multipart to singleparts`.

2. Use `Menu Processing / Toolbox / split with lines`, set the network (`road` layer) as input and the single part layer created in step 2 as `split layer`. Let's call the resulting layer of this operation `road_split`.

3. Now run the `Iso-Area as Pointcloud (from Layer)`, set the layer `road_split` created as `Network layer` and the `park` layer as `Startpoint layer` and select an `unique Point ID field`. Choose a `Size of Iso-Area` (maximum distance from the parks, using the network) and set the `Optimization criterion` to `Shortest Path (distance optimization)`. You can leave empty the rest of the settings.

4. In the resulting point-layer, select all points that correspond to a point in the address-layer. Use `select by expression` with this expression: `overlay_nearest( 'buildings', max_distance:=1)`. The `max_distance:=1` is a tolerence setting to find points even if (for rounding error or else) are not 100% exactly in the same place (as is often the case after processing) - adapt the distance (here: 1 [meter]) to your needs.

5. Use `Invert selection (Ctrl+R)` to select all points that do not represent a building. Then toggle editing, delete them. You're left with a point layer with the same points as you addresses, but with additional values for distance to next park (`cost`) and id of the nearest park (`origin_point_id`).

Screenshot: Green dots: parks; black lines: network (roads); red points: addresses = the layer resulting in step 6. It is labeled with the `cost` attribute created in step 4, indicating the distance in meters, using the network, form each address to the nearest park: Snapping points to the network

If your points (addresses, parks) are not yet snapped to the lines of the network layer called `road`, create a new point layer for each with this expression and then use these new layers for the steps described above. This works regardless of whether your addresses and parks layers are points, lines or polygons:

``````closest_point(
collect_geometries (
overlay_nearest(