# Find angle of segment of line geometry nearest to point

I have a layer of points (Waterfalls) and a layer of lines (Watercourses) with no linking information between them.

I am looking to use a QGIS expression to estimate the angle of the waterfall for the purpose of symbolising it.

The intention is to use the angle of the segment of the watercourse (line) nearest to the waterfall (point) as a proxy for the angle of the stream, and that the waterfall angle will be this rotated by 90 degrees - like the black line across the stream below.

I can easily find the geometry of nearest watercourse for a given waterfall using `overlay_nearest`:

`overlay_nearest('Watercourse',@geometry)`

However, I don't see an easy way of getting the nearest segment of that geometry, nor its angle. `segments_to_lines` would break the line into segments, but I'm not sure how to then get the closest.

Using `line_locate_point` and then `line_interpolate_angle` would work but seems a very indirect method. Hopefully someone can point out an alternative.

• Why do you consider `line_locate_poin`t and `line_interpolate_angle` to be an indirect method? I think it's the best in this case, quite straightforward Commented Nov 9, 2023 at 6:48
• My mathematical mind thought that `line_locate_point` / `line_interpolate_angle` lacked elegance. I was hoping for an easy way of identifying the closest segment. It appears that it's doable but not that easy. Commented Nov 9, 2023 at 21:20
• My geometrical mind thinks it's quite elegant... ;-) Commented Nov 9, 2023 at 21:32

If you specifically do not want to use `line_locate_point` and `line_interpolate_angle`, you can do it like so:

• First create an array of the segments as geometries.
• The distance from each segment to your waterfall points are calculated in a separate array and this is used to index the array of geometries to find the closest segment.
• The `main_angle` of the segment + 90 is then your perpendicular angle (in my case, set to the `Rotation` property of the 'line' simple marker type.
``````with_variable('geoms',
geometries_to_array(
segments_to_lines(
aggregate(
'watercourse',
'collect',
@geometry
)
)
),
with_variable(
'dists',
array_foreach(@geoms, distance(@element, @geometry)),
main_angle(array_get(@geoms, array_find(@dists, array_min(@dists)))) + 90
)
)
``````

Note: the `geometries_to_array` function was added relatively recently. For earlier versions of QGIS the following snippet can be substituted for `with_variable('geoms', geometries_to_array(segments_to_lines(...))`

``````with_variable('segments',
segments_to_lines(aggregate('watercourse', 'collect',   @geometry)),
with_variable('geoms',
array_foreach(
generate_series(1, num_geometries(@segments)),
geometry_n(@segments, @element)
),

...

)
)
``````

However, I would agree with @Babel (credit for a simplified expression) that it is less fiddly to use `line_locate_point` and `line_interpolate_angle`:

``````line_interpolate_angle(
overlay_nearest('watercourse',  @geometry)[0],
line_locate_point(
overlay_nearest('watercourse', @geometry)[0],
@geometry
)
) + 90
``````

Notes: the positions of the waterfall points were snapped to the watercourses using a Geometry Generator expression: `closest_point(overlay_nearest('watercourse', @geometry)[0], @geometry)`

• Yeah, it does seem simpler to stick with `line_interpolate_angle`! For simplifying that expression slightly, I'd gone with: `with_variable('watercourse',overlay_nearest('watercourse',@geometry)[0], line_interpolate_angle(@watercourse,line_locate_point(@watercourse,\$geometry)))-90` Commented Nov 9, 2023 at 21:28