If you would like consider R as a tool, then below approach can be used:
First of all let's find some way and place for camera. I will use OSM data - finding bounding box and highways in my village.
library(osmdata)
library(tidyverse)
library(sf)
Lbb <- getbb("Lubnów, Oborniki Śląskie, Poland", format_out = "matrix")
highways <- opq (Lbb, timeout = 60) |>
add_osm_feature (key = "highway") |>
osmdata_sf()
Let's prepare a plot area and plot the highways:
plot(x = Lbb[1], y = Lbb[2], type = "n", xlim = c(Lbb[1], Lbb[3]), ylim = c(Lbb[2], Lbb[4]))
plot(highways$osm_lines$geometry, add = TRUE)

Let's create our camera position (p1) and construct a line upwards (0 deg), where p2 is the line end point:
p1 <- st_point(x = c((Lbb[3]+Lbb[1])/2, (Lbb[4]+Lbb[2])/2))
p2 <- st_point(x = c(p1[1], Lbb[4]+1))
plot(p1, pch = 16, col = "red", add = TRUE)
l <- st_linestring(c(p1, p2))
plot(l, add = TRUE, col = "green")

Let's define rot function for line rotate (taken from sf
vignette: https://r-spatial.github.io/sf/articles/sf3.html#affine-transformations) and create l2 which is rotated by 45 deg (pi/4)
rot = function(a) matrix(c(cos(a), sin(a), -sin(a), cos(a)), 2, 2)
l2 <- (l-p1) * rot(pi/4) + p1
plot(l2, col = "orange", add = TRUE)

And finally, let's find all highways which are intersects by l2 (using st_join
), find their intersections (st_intersection
), calculate the distance to our camera (st_distance(P1, intersection point)
), arrange
them increasingly and take the first result head(1)
as the closest one.
l2 <- st_as_sf(st_sfc(l2))
h <- st_as_sf(highways$osm_lines)
st_crs(l2) <- st_crs(h)
P1 <- st_as_sf(st_sfc(p1))
st_crs(P1) <- st_crs(h)
h |>
st_join(l2, left = FALSE) |>
select(osm_id, geometry) |>
st_intersection(l2) |>
rowwise() |>
mutate(distance = mapply(function(x) st_distance(P1, x), st_as_sf(geometry))) |>
arrange(distance) |>
head(1)
which gives us:
#> Simple feature collection with 1 feature and 2 fields
#> Geometry type: POINT
#> Dimension: XY
#> Bounding box: xmin: 16.88842 ymin: 51.26244 xmax: 16.88842 ymax: 51.26244
#> Geodetic CRS: WGS 84
#> # A tibble: 1 × 3
#> # Rowwise:
#> osm_id geometry distance
#> <chr> <POINT [°]> <dbl>
#> 1 105505165 (16.88842 51.26244) 50.0
and we can add it to plot
[...] |>
select(geometry) |>
plot(add = TRUE)

Then it can be extended for all your cameras either in loop, or creating a function and applying it to them. If you have shp
files, you can read them with st_read
. Just make sure CRS systems of ways and camera positions are the same.
Hope it makes sense.
Created on 2022-02-23 by the reprex package (v2.0.1)