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.
- 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,
radians(@element)
)
),
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:
Convert the lines to single parts using Menu Vector / Geometry tools / Multipart to singleparts
.
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
.
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.
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.
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(
'road',
$geometry
)
),
$geometry
)